Piceli
Kubernetes infrastructure as typed Python: model it, plan it, apply it safely, and observe it
Documentation: https://docs.pynenc.org/projects/piceli
Source Code: https://github.com/pynenc/piceli
Piceli describes a Kubernetes application in typed Python, shows you exactly
what would change in the cluster, and applies only the plan you approved. Every
change is journaled, so an interrupted deploy resumes where it stopped and a
bad release rolls back. One command, piceli deploy, takes an app from source
to a running, checked release; piceli status and piceli access tell you
whether it is up and forward its ports to your laptop.
It is a Python-native alternative to hand-maintained YAML, Kustomize overlays
and Helm templates, and it still accepts plain YAML/JSON and kubernetes
client objects, so you can migrate gradually.
Status: pre-alpha. APIs change between releases, always with a changelog entry. Each documentation page states its maturity (stable, preview or experimental); the roadmap lists them all.
What's new in 0.4.0
piceli deploy: build, deliver by digest, plan, apply and check in one journaled, resumable run that skips every unchanged stage.- Post-deploy checks (
http,exec,metric, Python) with automatic rollback when one fails. - Field-level diffs and true no-op plans (
piceli release diff). piceli statusandpiceli access: is the app up, which URLs, and supervised loopback port forwards declared in the model.piceli import live|yaml: turn a running namespace or a folder of manifests into a typed app module.- One engine: the legacy delete-and-recreate engine is gone; every change goes through server-side apply, the journal and resume.
See the changelog for the complete list, including breaking changes.
Installation
pip install piceli # or: uv add piceli
Python 3.12 or later. Optional extras: piceli[telemetry] (OTLP deployment
telemetry) and piceli[gcp] (GKE cluster helpers). The PyPI release can lag
behind main while the project is pre-alpha; to follow main:
pip install git+https://github.com/pynenc/piceli.git.
Quick start
You need a cluster reachable through an explicit kubeconfig file, and
kubectl on your PATH (for checks and port forwards). A disposable
kind cluster works:
kind create cluster --name hello --kubeconfig hello.kubeconfig
kubectl --kubeconfig hello.kubeconfig create namespace hello
Describe the app, where it runs and how to check it in app.py:
from piceli import App, Checks, Pipeline, Target
target = Target.kubeconfig(
"hello.kubeconfig", # an explicit file; never ~/.kube/config
context="kind-hello", # an explicit context; never current-context
namespace="hello",
)
app = App("hello")
web = app.deployment(
"web",
image=(
"docker.io/library/nginx:1.27"
"@sha256:6784fb0834aa7dbbe12e3d7471e69c290df3e6ba810dc38b34ae33d3c1c05f7d"
),
ports=[80],
ready=app.probe.http("/", 80),
)
app.service(web, port=80, access=app.access.forward(local=18080, health="/"))
pipeline = Pipeline(app, target, checks=Checks.http(web, "/", expect=200))
Render it, review the plan, approve that exact plan, and reach the app:
piceli render app.py:app --namespace hello # the manifests; never contacts a cluster
piceli deploy app.py:pipeline --plan # what would change, and a combined hash
piceli deploy app.py:pipeline --approve <combined-hash> # runs exactly that plan
piceli status app.py:pipeline # is it up, and at which URLs
piceli access app.py:pipeline # forwards http://127.0.0.1:18080/
Run piceli deploy again without changes and the plan reports no changes, so
nothing is applied. Change the app and only what changed moves. If a run is
interrupted,
piceli deploy app.py:pipeline --resume continues it.
Next steps:
- Getting started walks through the same app step by step.
- Deploy an app from source adds pinned image builds and delivery to a registry or node.
- Releases from a spec
covers
release.toml, adoption, secrets, rollback and resume. - From kubectl scripts to Piceli imports what already runs in a namespace.
Key features
- Typed apps: Deployments, Services, config, secrets, volumes and network
policies declared with
piceli.App, validated as you write them. Templates,kubernetesclient objects and YAML/JSON can be mixed into the same release.piceli renderprints plain manifests without a cluster. - Plan before apply: every change is computed against the live cluster (with server-side dry runs, so defaults are not reported as changes), shown field by field, and executed only with an explicit approval of its hash.
- One recoverable engine: server-side apply with UID and resourceVersion
preconditions, dependency ordering, readiness waits and a durable journal.
resume,stopandrollbackwork on every release. - Safe by default: Piceli only talks to the kubeconfig file and context you name, never changes objects it does not own unless you adopt them, never prunes Namespaces, PersistentVolumes, PersistentVolumeClaims or Secrets, and never prints secret values.
- Source to release: pinned containerized builds, source identity, and image delivery by digest to an OCI registry, a node-local registry or a node's containerd. Nothing is pushed or deployed implicitly.
- Checks and rollback:
http,exec,metricand Python checks run after every apply; a failed check can re-apply the previous release automatically. - Status and access:
piceli statussays whether the app is up and how to reach it;piceli accesssupervises the port forwards the model declares. - Import:
piceli import liveandpiceli import yamlgenerate a typed module from running objects or existing manifests. - Built for agents and CI: machine output as JSON on stdout, fixed error
codes explained by
piceli explain, the whole command tree with side effects and approval rules frompiceli help-json, and a public fake Kubernetes API (piceli.testing) for your own tests.
For coding agents
Start with Using Piceli from an agent:
which commands only read, which need the owner's approval, the output contract
and how to recover from errors. The documentation index for language models is
llms.txt. To
change Piceli itself, read AGENTS.md.
Requirements
- Python 3.12 or later.
- A kubeconfig file with a context for the target cluster. Piceli never uses
~/.kube/config,KUBECONFIGor the current context implicitly: the file and context are named in the pipeline, the release spec or on the command line. kubectlonPATHfor checks,piceli accessand the node-local registry;dockerwithbuildxfor containerized builds.
Contributing
Contributions are welcome. See CONTRIBUTING.md for setup, tests and pull request guidelines.
Community and support
- GitHub Issues: bug reports, feature requests and questions
- Documentation: guides, command reference and error codes
- Roadmap: feature maturity and direction
- Security: report vulnerabilities privately, see SECURITY.md
Piceli is developed alongside Pynenc, but it does not depend on it and works with any Kubernetes workload.
License
Piceli is made available under the MIT License.
Release files for piceli 0.4.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| piceli-0.4.1.tar.gz | 5.2 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| piceli-0.4.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 5.8 MB
Release files / piceli-0.4.1.tar.gz
| Download URL | piceli-0.4.1.tar.gz |
|---|---|
| Size | 5.2 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8f7685f59c43acb0ffe8220a2d976cd03c0c85b5379369fb1ee4332e7058576d
|
|
BLAKE2b-256 checksum How to use checksums |
f97ee01f2b9790c069d4acb87ddff0b72436305043ecbc0e5ac48cbc0f471f2e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","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}
|
Release files / piceli-0.4.1-py3-none-any.whl
| Download URL | piceli-0.4.1-py3-none-any.whl |
|---|---|
| Size | 552.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a32bcf2d8522a900db3155dc46d0301c05cd7467e8928e922d8d6d35be3eb271
|
|
BLAKE2b-256 checksum How to use checksums |
1089e802a020601a744b7f2764a49fc1ffed5c63fb99947882902d97a3687aa3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","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}
|