{"id":46194790,"url":"https://github.com/joshuajerome/cutip","last_synced_at":"2026-05-13T18:16:39.404Z","repository":{"id":341162715,"uuid":"1162836098","full_name":"joshuajerome/cutip","owner":"joshuajerome","description":"A deterministic framework for building and orchestrating container workloads.","archived":false,"fork":false,"pushed_at":"2026-04-14T19:31:47.000Z","size":2203,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"integration","last_synced_at":"2026-04-14T21:30:43.697Z","etag":null,"topics":["automation","cli","containers","podman","python","workflow","yaml"],"latest_commit_sha":null,"homepage":"https://joshuajerome.github.io/cutip/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/joshuajerome.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-20T18:54:58.000Z","updated_at":"2026-04-14T19:29:42.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/joshuajerome/cutip","commit_stats":null,"previous_names":["joshuajerome/cutip"],"tags_count":37,"template":false,"template_full_name":null,"purl":"pkg:github/joshuajerome/cutip","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshuajerome%2Fcutip","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshuajerome%2Fcutip/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshuajerome%2Fcutip/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshuajerome%2Fcutip/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joshuajerome","download_url":"https://codeload.github.com/joshuajerome/cutip/tar.gz/refs/heads/integration","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshuajerome%2Fcutip/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32169657,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-23T02:19:40.750Z","status":"ssl_error","status_checked_at":"2026-04-23T02:17:55.737Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["automation","cli","containers","podman","python","workflow","yaml"],"created_at":"2026-03-03T02:14:57.044Z","updated_at":"2026-04-23T07:00:35.498Z","avatar_url":"https://github.com/joshuajerome.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CUTIP\n\n[![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-3776ab)](https://www.python.org/downloads/)\n[![Pydantic v2](https://img.shields.io/badge/pydantic-v2-e92063)](https://docs.pydantic.dev/latest/)\n[![uv](https://img.shields.io/badge/uv-package_manager-6e44ff)](https://github.com/astral-sh/uv)\n[![Runtime](https://img.shields.io/badge/runtime-podman%20%7C%20docker-892ca0)](https://joshuajerome.github.io/cutip/getting-started/installation/)\n[![CI](https://github.com/joshuajerome/cutip/actions/workflows/ci.yml/badge.svg)](https://github.com/joshuajerome/cutip/actions/workflows/ci.yml)\n[![Docs](https://img.shields.io/badge/docs-github%20pages-0969da)](https://joshuajerome.github.io/cutip)\n\nAutomate multi-step operations using containers as reproducible execution environments.\n\nCUTIP is a workflow automation framework. You define container infrastructure as typed YAML artifacts, write orchestration logic in Python, and CUTIP handles the lifecycle: pre-build file generation, container startup ordering, health-check loops, and post-deployment verification. Every artifact is validated statically before any container runtime is contacted.\n\n**Containers are the medium, not the goal.** The task is the goal — SSH into a VM, configure a service, patch a deployment, start a dev environment. CUTIP makes that operation structured, validated, and reproducible.\n\n## What cutip is NOT\n\n- **Not a Docker replacement.** cutip uses Docker or Podman as backends. It does not build images differently or replace `docker run`.\n- **Not a Kubernetes orchestrator.** cutip manages local container workloads. For K8s operations, use [cutip-blocks](https://github.com/joshuajerome/cutip-blocks) which provides kubectl blocks over SSH.\n- **Not a CI/CD system.** cutip runs workflows locally or in containers. It complements CI — it doesn't replace GitHub Actions or Jenkins.\n- **Not a Docker Compose replacement for simple stacks.** If you're running postgres + redis + your app with no custom startup logic, use Compose. cutip solves a different class of problems.\n\n## Who is this for\n\n- DevOps engineers automating VM or Kubernetes operations that span multiple tools (SSH, kubectl, REST APIs)\n- Teams that outgrew bash scripts but don't need the weight of Ansible\n- Developers who want reproducible multi-step procedures with validation, hooks, and visual inspection\n- Anyone who needs to generate config files, exec into containers during startup, or branch on health state\n\n## The model\n\n```\nImageCard   ─┐\nNetworkCard ─┘──\u003e  ContainerCard  ──\u003e  Unit  ──\u003e  Group  ──\u003e  workflow.py\n```\n\n| Layer | What it is |\n|---|---|\n| **Card** | A YAML file defining one container resource (image, network, or container config). Validated by Pydantic v2. |\n| **Unit** | A named container instance — references one ContainerCard + optional pre/post hooks. |\n| **Group** | A collection of Units + a `workflow.py`. The executable artifact: `cutip run \u003cgroup\u003e`. |\n| **Workflow** | A Python function `main(ctx)` that starts containers, runs health checks, and orchestrates. Full Python — no DSL. |\n\nEvery artifact is a versioned YAML file (`apiVersion: cutip/v1`). Every ref is resolved and validated before any backend is contacted.\n\n## Install\n\n```shell\npip install cutip\n```\n\n## Quick start\n\n```shell\ncutip init              # scaffold a workspace with example projects\ncutip validate          # static validation — no container runtime needed\ncutip plan hello-world  # dry-run — print what would happen\ncutip run hello-world   # validate → connect → execute workflow\n```\n\n## Before and after\n\n**Before (bash script):**\n```bash\n#!/bin/bash\nssh root@$VM_IP \"kubectl exec -n prod deploy/web -- cat /opt/config/handler.py \u003e /root/patches/handler.py\"\nssh root@$VM_IP \"sed -i 's|get_host(req)|localhost:4000|g' /root/patches/handler.py\"\nssh root@$VM_IP \"chmod 777 /root/patches/handler.py\"\nssh root@$VM_IP \"kubectl get deployment -n prod web -o yaml | python3 -c 'import sys,yaml; ...' | kubectl apply -f -\"\nssh root@$VM_IP \"kubectl rollout status deployment -n prod web --timeout=120s\"\n# Hope nothing went wrong. No validation. No rollback. No visibility.\n```\n\n**After (cutip workflow):**\n```python\n@orchestrator\ndef main(ctx):\n    container.start(ctx, container=\"ops-runner\")\n\n    with ssh.session(ctx, container=\"ops-runner\",\n                     host=vm[\"ip\"], username=\"root\", password=pw) as sesh:\n\n        stage(\"Pre-op Validation\")\n        ssh.probe(ctx, sesh)\n        k8s.get_deployment(ctx, sesh, namespace=\"prod\", deployment=\"web\")\n\n        stage(\"Operations\")\n        patch_handler(ctx, sesh)\n        apply_deploy(ctx, sesh)\n\n        stage(\"Post-op Validation\")\n        k8s.rollout_status(ctx, sesh, namespace=\"prod\", deployment=\"web\")\n\n    container.stop(ctx, container=\"ops-runner\")\n```\n\nEvery step is a named `@action`. The workflow is validated before execution. Failed steps report which action and stage broke. The entire pipeline is visible as a DAG in [CUTIP Desktop](https://github.com/joshuajerome/cutip-desktop).\n\n## How it compares\n\n| | Bash script | Docker Compose | Ansible | CUTIP |\n|---|---|---|---|---|\n| **Validation** | None | Runtime only | YAML lint | Static graph validation — no runtime needed |\n| **Reproducibility** | Hope-based | Image tags | Playbook idempotency | Deterministic: same YAML + same workflow = same result |\n| **Startup ordering** | Sequential commands | `depends_on` with health poll | Task ordering | Python: exec into container, branch on result |\n| **Pre-build hooks** | Makefile target | None | None | `pre_build(ctx)` per unit |\n| **Post-start hooks** | None | None | Handlers (limited) | `startup(ctx)` per unit |\n| **Secrets** | `.env` or hardcoded | `.env` flat substitution | Vault / vars | `secrets.yaml` with fail-fast validation |\n| **Visual inspection** | `set -x` | None | `--verbose` | DAG visualization in [CUTIP Desktop](https://github.com/joshuajerome/cutip-desktop) |\n| **Migration** | Manual | — | Manual | `cutip from-compose` converts any compose file |\n\n## Ecosystem\n\n| Project | Description |\n|---|---|\n| [cutip](https://github.com/joshuajerome/cutip) | Core framework — YAML artifacts, Python workflows, CLI |\n| [cutip-blocks](https://github.com/joshuajerome/cutip-blocks) | Reusable workflow blocks — SSH, kubectl, file ops, container lifecycle (34 blocks, 9 categories) |\n| [cutip-desktop](https://github.com/joshuajerome/cutip-desktop) | Visual companion — DAG visualization, artifact inspection, container management, observability |\n\n## CLI\n\n| Command | Description |\n|---|---|\n| `cutip init` | Scaffold workspace with example projects |\n| `cutip validate` | Static graph validation (no runtime needed) |\n| `cutip plan \u003cgroup\u003e` | Dry-run: print execution table |\n| `cutip run \u003cgroup\u003e` | Validate, connect, execute workflow |\n| `cutip tree` | Print workspace artifact tree |\n| `cutip show \u003ctype\u003e \u003cname\u003e` | Dump a resolved artifact |\n| `cutip from-compose \u003cfile\u003e` | Convert a Docker Compose file to cutip artifacts |\n| `cutip secrets set/list/check` | Manage secrets.yaml |\n\n## Documentation\n\n**[joshuajerome.github.io/cutip](https://joshuajerome.github.io/cutip)**\n\n- [Why CUTIP?](https://joshuajerome.github.io/cutip/getting-started/why-cutip/) — detailed comparison with Docker Compose\n- [Concepts](https://joshuajerome.github.io/cutip/concepts/overview/) — cards, units, groups, lifecycle, graph resolution\n- [Quickstart](https://joshuajerome.github.io/cutip/getting-started/quickstart/) — end-to-end walkthrough\n- [Use Cases](https://joshuajerome.github.io/cutip/guides/use-cases/) — real-world examples\n\n## License\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoshuajerome%2Fcutip","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoshuajerome%2Fcutip","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoshuajerome%2Fcutip/lists"}