Skip to main content
Zuke

Zuke for Python: author your build as typed Python, run it on the Zuke engine. Your build and your CI are one typed file — and your agent can run it.

CI Release AI review PyPI Python versions Provenance: PEP 740 Typed: pyright strict uv Ruff Runs on @zuke/engine License: MIT Part of Zuke

Zuke is a code-first, strongly-typed build automation system: a build is a class whose fields are targets, dependencies are references the type checker sees, and the same file generates your CI and serves your build to AI agents. This package brings that model to Python. Write the build as typed Python, and the Zuke engine runs it: scheduling, retries, timeouts, cancellation, durable runs, locks, caching, services, CI generation, the MCP server and every tool wrapper live there, implemented once. This package is the thin SDK that describes your build to the engine and runs your target bodies when asked.

Five minutes to a typed Python build

1. Install the zuke CLI — pick one. Every route is the same CLI; see the main repository's install guide.

deno install -A -g -n zuke jsr:@zuke/cli   # any OS, with Deno
brew install zuke-build/tap/zuke           # macOS, Linux
choco install zuke                         # Windows

2. Scaffold a Python project and run it:

zuke setup --sdk python   # build.py, zuke.json pinning @zuke/engine, the launchers
zuke                      # run the build
zuke --list               # every target, with its description and dependencies

You need uv; the scaffolded build.py carries inline script metadata, so uv run build.py installs this package by itself, with no project file of its own. Here is a build after replacing the sample target with real work:

from zuke import Build, ci, parameter, run, target
from zuke.tools.docker import DockerTasks


class CI(Build):
    tag = parameter("image tag").default("dev")
    pipeline = ci().path(".github/workflows/ci.yml")

    lint = (
        target().description("ruff").executes(lambda ctx: ctx.sh("ruff", "check", "."))
    )
    test = target().depends_on(lint).executes(lambda ctx: ctx.sh("pytest", "-q"))
    image = (
        target()
        .depends_on(test)
        .executes(
            lambda ctx: DockerTasks.build(
                ctx, lambda s: s.tag(f"app:{tag.value}").file("Dockerfile")
            )
        )
    )


run(CI)

zuke image runs lint, test and image in order, every command spawned by the engine. zuke graph --output=html draws the graph, zuke generate-ci writes the workflow the ci() field declares, and zuke mcp serves the whole build to an agent as typed tools.

Why Zuke for Python

  • Typed, refactor-safe dependencies. depends_on(lint) is a reference to the sibling field, not a string: pyright sees it, a rename moves every use, and a typo is an error before anything runs.
  • Every tool, typed. zuke.tools holds a facade for each of the engine's 50+ wrappers — Docker, Kubernetes, Terraform, uv-adjacent tooling, the cloud CLIs, the AI reviewers — generated from the engine's own tool spec, so the Python surface matches the TypeScript one setter for setter.
  • One engine, every guarantee. Argv-only command execution, output capture and secret redaction, dry runs, timeouts and cancellation, durable run records with resume, cross-run locks, caching and services are all done once, in the engine, for every SDK. The Python side cannot drift from them.
  • Never write CI YAML again. Declare the pipeline in the build and the engine renders GitHub Actions, GitLab CI, Azure Pipelines or Bitbucket YAML; generate-ci --check fails CI when the committed file drifts.
  • Let your agent run the build. zuke mcp serves your targets, parameters and graph over the Model Context Protocol, exactly as for a TypeScript build.
  • No runtime dependencies. The package is the standard library only, and strict-typed end to end.

Install

What How
The zuke CLI deno install -A -g -n zuke jsr:@zuke/cli, brew install zuke-build/tap/zuke, choco install zuke
This package, into an existing project uv add --dev zuke, or pip install zuke
A new project zuke setup --sdk python, which writes build.py, zuke.json and the launchers

Python 3.12 or newer. The engine runs on Deno: the zuke CLI finds or installs it, and so do the committed ./zuke and zuke.ps1 launchers, which download a pinned, checksum-verified Deno on first use. zuke.json pins the exact @zuke/engine release a project runs on; zuke upgrade --engine moves it.

On a machine without the CLI, such as a CI runner, the launchers run the build the same way: ./zuke ci, or ./zuke.ps1 ci on Windows. The generated workflows call them.

How it works

zuke <target>  ─▶  @zuke/engine (the pinned release, on Deno)
                      │  starts the worker zuke.json names: uv run build.py
                      ▼
                   build.py  ◀── JSON-RPC 2.0 over loopback ──▶  engine
                   (this SDK)     build.describe, target.run,     scheduling, exec,
                                  exec, tool.call, state, …       wrappers, CI, MCP

The engine starts your build file as a worker and asks it for the graph. When a target's turn comes, the engine asks the worker to run its body; the body's ctx.sh(...) and every *Tasks call travel back to the engine, which spawns the process or runs the real wrapper under the run's dry-run, redaction and cancellation. The worker's stdout and stderr become log lines, so a stray print cannot corrupt the protocol. The protocol and its conformance cases are defined in the main repository (packages/engine); this package replays every case of the engine release it pins.

The authoring surface

target() carries every setting the engine schedules by (depends_on, retry, timeout, before, after, triggers, on_failure, …); parameter() has the string, number, boolean and list kinds, with .value resolved by the engine from flags and environment variables, and .secret() redacts one everywhere; group() names a parallel batch; service() declares a service with start, ready and stop phases; ci() declares a CI file; and run() makes the file a worker.

A body gets a ctx: await ctx.sh(...) runs a command through the engine and raises CommandError on a non-zero code; ctx.state and ctx.state_of(...) read and write durable state; ctx.outcome_of, ctx.outcomes, ctx.summary, ctx.secret, ctx.log, ctx.plan and ctx.signals are the rest of what the engine serves a body. A target may declare .condition(...), .cache_key(...), .lock(...), .waits_for(...) and .validate_during(...), and a Build overrides on_start, on_target_start, on_target_end and on_finish for hooks.

zuke.tools.<wrapper> is a facade per engine wrapper — zuke.tools.docker, zuke.tools.deno, zuke.tools.gh and the rest. DockerTasks.build(ctx, lambda s: ...) records the setters the lambda calls and sends the engine one tool.call, which runs the real wrapper with the worker's environment and directory. The full catalogue, with every task and setting, is the main repository's tool reference.

Supply chain

Every release is built by this repository's own Zuke build and uploaded to PyPI with trusted publishing: no API token exists. From 1.0.1, each file also carries a PEP 740 provenance attestation, signed from the release job's identity, which PyPI verifies back to zuke-build/zuke-python's release.yml; see the Security tab of a release on PyPI. Actions are pinned by commit SHA, the engine and every wrapper it loads run frozen against the committed deno.lock, and uv.lock locks the development environment. See SECURITY.md.

Documentation

The documentation lives in the main repository:

The Python surface itself is documented by its docstrings, and pyright and your editor read them. The website renders them as the Python API reference, with a Python guide beside it: zuke api_reference generates the reference from the docstrings, and each release syncs it to the website.

Development

uv is the only tool you need.

uv sync          # the locked environment
zuke ci          # the gate: format check, lint, pyright strict, tests at 95%+
zuke --list      # every target of build.py, this repository's own Zuke build

The gate is itself a Zuke build, build.py, run by @zuke/engine at the version zuke.json pins; ./zuke ci runs the same gate without the CLI, and CI runs it on Ubuntu, macOS and Windows. The tool facades are generated from the engine's tool spec, vendored under spec/, and facades_check fails the gate when they drift. The engine, every wrapper it imports, and their @zuke/core run frozen against deno.lock; zuke lock rewrites it. The same AI reviewers the main repository runs review this repository's pull requests, from build.py's review target through zuke.tools.ai: the SDK's build is reviewed by the SDK.

Contributing

Contributions are welcome! Start with CONTRIBUTING.md for the workflow, and please be mindful of the Code of Conduct. AGENTS.md holds the coding standards — pyright strict, no Any or cast, 95%+ coverage, hermetic tests. Every change starts with an issue. A change to the engine, the protocol or a tool wrapper belongs in the main repository, and reaches this one through the vendored spec and the pinned engine.

Security

zuke-python runs inside other people's build pipelines, so supply-chain integrity is the primary concern. Please report a vulnerability privately, through the Security tab's "Report a vulnerability"; see SECURITY.md for the posture and the process, and the main repository's policy for the engine.

License

MIT — see LICENSE.

Acknowledgements

  • NUKE and its creator Matthias Koch — the code-first, strongly-typed build model Zuke is an homage to.
  • uv, Ruff and pyright — the toolchain this package is built, linted and type-checked with.
  • Deno and JSR, which the engine runs on and ships from, and PyPI and the PyPA, whose trusted publishing and attestations sign this package.

Community & contact

Questions, ideas, or just want to say hi? Open an issue for the Python side, or one in the main repository for everything else, or reach out:

Website Email Blog X LinkedIn Mastodon Threads Bluesky Linktree

Swag, sponsoring, star history & contributors

Swag

Zuke has a swag shop! Grab some Zuke-branded apparel and accessories and wear the build:

Zuke swag shop

Sponsoring

If Zuke saves you time, you can support its development through GitHub Sponsors, Buy Me a Coffee or Patreon — the Sponsor button at the top of the repository lists them all.

Star history

RepoStars

If Zuke for Python is useful to you, consider starring this repository and the main one — it helps others find the project. ⭐

Contributors

Contributors

Metadata

Release files for zuke 1.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for zuke 1.2.0
File Size Uploaded Provenance Actions
zuke-1.2.0.tar.gz 548.1 kB With provenance Details for zuke-1.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for zuke 1.2.0
File Interpreter ABI Platform Actions
zuke-1.2.0-py3-none-any.whl Python 3 none any Details for zuke-1.2.0-py3-none-any.whl

Total release size: 853.1 kB

Release files / zuke-1.2.0.tar.gz

Download URL zuke-1.2.0.tar.gz
Size 548.1 kB
Tags Source
SHA-256 checksum
How to use checksums
1b8711ed5f96601b378594cca626ba169d1ca5ee041a5e7cd7af087b5f48e5ad
BLAKE2b-256 checksum
How to use checksums
640ed88423669d6147fff117daf9d465b4f02abdfc8cf635952a2309e9199b17
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","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}

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 3, 2026.

Transparency log

Release files / zuke-1.2.0-py3-none-any.whl

Download URL zuke-1.2.0-py3-none-any.whl
Size 305.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8955d2b168fd7a4fcf5a5cd0898b42d4b9abc9ab3ebbc6f46d4d511a8e8eb0c2
BLAKE2b-256 checksum
How to use checksums
3889328b9d84c4408bca29618b3b635e506a0d1a90a4d545a45920d2c49c3079
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","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}

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 3, 2026.

Transparency log

Security for zuke 1.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for zuke-1.2.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 3, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page