Pacto is to service operations what OpenAPI is to HTTP APIs.
A service's operational behavior — interfaces, dependencies, runtime semantics, configuration and readiness — is scattered across Helm values, wikis and dashboards, and drifts from what's actually running. Pacto captures it once in a validated, versioned contract (pacto.yaml), distributes it through your existing OCI registry and lets pacto diff catch breaking changes while the operator catches runtime drift. It doesn't replace OpenAPI, Helm, Terraform, Backstage or Kubernetes — it adds the operational contract layer between them, composing the interfaces you already own and adding what no single one does: ownership, dependencies, compatibility and readiness over time.
Composed across a platform, those contracts become more than per-service files: Pacto turns platform knowledge into a versioned, verifiable operational graph that humans, automation and agents can reason over — its four capabilities are Diff · Graph · Enforce · Verify. Internal Developer Platforms make platform capabilities consumable by humans through portals, golden paths, catalogues and workflows; Pacto makes platform knowledge consumable by machines through contracts, relationships, constraints, tools and evidence. Pacto is not an IDP, a portal, a deployment engine or an authorization system — it is the machine-readable operational layer over a platform, and a human portal and an agent can consume the same Pacto graph.
Documentation · Quickstart · Specification · Examples · Live demo
Why Pacto exists — MANIFEST.md
flowchart LR
DEV([Developer]) --> C
OA[OpenAPI spec] -. composed .-> C
JS[Config JSON Schema] -. composed .-> C
C["📋 pacto.yaml<br/>operational contract"] --> R[(OCI registry)]
R --> P["Platforms and tools<br/>CI · Kubernetes · Backstage · Crossplane"]
Pacto composes the interfaces you already own into one versioned contract, distributes it like a container image and lets whatever consumes your services — platforms, CI, runtime controllers and increasingly autonomous agents — read it instead of reverse-engineering it.
Underneath the products is one model. The contract declares intent; a collector observes a running environment and emits Evidence; the pure engine evaluates Contract × Evidence into Findings; consumers surface or act on them.
flowchart TB
A["Author intent<br/>pacto.yaml"] --> C["Contract"]
R["Running environment"] --> COL["Collector"]
COL --> E["EvidenceSet"]
C --> EV["Evaluate"]
E --> EV
EV --> OUT["Findings + Coverage"]
The stable extension boundary is the EvidenceSet, not a collector interface: a collector is any component that produces a valid EvidenceSet the engine can evaluate. The Kubernetes collector is the first shipped integration; other collectors may live inside or outside this monorepo. Pacto is modular through a stable Evidence schema — not a dynamically pluggable collector runtime. See Collectors and the evidence boundary.
The CLI, dashboard and Kubernetes operator are products built on that model — not the architecture itself. The operator is the host around the Kubernetes collector; the engine never queries Kubernetes.
flowchart LR
CLI["CLI · design-time and CI<br/>init · validate · diff · doc · push"] --> R[(OCI registry)]
R --> DASH["Dashboard · anytime<br/>graph · ownership · SBOM · readiness · docs"]
R --> OP["Operator · in-cluster<br/>hosts the Kubernetes collector · track · verify"]
OP -. runtime state .-> DASH
No sidecars and no central control plane: the CLI uses your existing OCI registry, the operator watches CRDs and the dashboard merges every source — local, OCI, Kubernetes and cache — into one view.
# Author and publish a contract (install is below)
pacto init my-service && cd my-service # scaffold a contract bundle
pacto validate . # 3-layer validation
pacto push oci://ghcr.io/acme/svc-pacto # tag inferred from service.version
# Catch breaking changes in CI
pacto diff oci://ghcr.io/acme/svc:1.0 oci://ghcr.io/acme/svc:2.0
# Explore everything in a browser
pacto dashboard # auto-detects local, OCI and K8s sourcesThe Quickstart goes from zero to a published contract in about five minutes, using a throwaway local registry so you need no account.
pactoVersion: "2.0"
service:
name: payments-api
version: 2.1.0
owner:
team: payments
dri: alice
interfaces:
- name: rest-api
type: openapi
ref: interfaces/openapi.yaml # points at your existing OpenAPI spec
visibility: public
dependencies:
- name: auth
ref: oci://ghcr.io/acme/auth-pacto:2.0.0
required: true
compatibility: "^2.0.0"Only pactoVersion and service are required — everything else (runtime semantics, configuration, policies and readiness) is opt-in. Each interface's ref points at a schema you already own, so a contract composes your interfaces rather than redefining them. See the Contract Reference for the full schema.
Bump a version, remove an endpoint, drop a config property — pacto diff classifies each and fails CI before the merge:
$ pacto diff oci://ghcr.io/acme/svc:1.0 oci://ghcr.io/acme/svc:2.0
Classification: BREAKING
Changes (3):
[NON_BREAKING] service.version (modified): service.version modified [1.0.0 -> 2.0.0]
[BREAKING] openapi.paths[/predict] (removed): API path /predict removed [- /predict]
[POTENTIAL_BREAKING] schema.properties.model_path (removed): schema.properties.model_path removed [- map[type:string]]
breaking changes detected # printed to stderr; non-zero exit gates the mergeEverything a contract enables, from one artifact:
- Dependency graph — transitive service relationships and blast radius (the downstream services a change can affect), recursively resolved
- Ownership registry — every service by team and DRI (directly responsible individual), with per-owner compliance and readiness
- SBOM inventory — SPDX / CycloneDX package inventory and package-level diffs across versions
- Operational docs —
pacto docrenders Markdown, an offline dashboard-grade HTML site or an interactive API explorer (--ui swagger, rendered with Scalar) - Readiness scoring — operational-readiness assessment per service, surfaced in the fleet view
- Runtime verification — with the operator, whether deployed workloads still match their contract
- OCI distribution — push/pull to GHCR, ECR, ACR, Docker Hub and Harbor with local caching; a digest reference is immutable. Pacto does not sign bundles or check signatures on them, so add cosign or Notary if your supply chain needs it — what Pacto does sign is evidence envelopes (Ed25519, verification always on) and its own published chart and image
- Reproducibility and supply chain —
pacto.lockfor pinned resolution, gitignore-style.pactoignorefor packaging - Extensibility — out-of-process plugins generate deployment artifacts;
pacto mcpexposes contract operations to Claude, Cursor and Copilot
The dashboard merges local, OCI and Kubernetes sources into one fleet view; deploy the container image alongside the operator to combine runtime state with contract data.
Pacto composes the interface tools it sits between (OpenAPI, config schemas) and complements deploy tools (Helm, Terraform). It gets compared just as often to the platform-engineering tier — the orchestrators, provisioners and portals that act on a service. Pacto is not one of them: its job is four verbs over a single versioned OCI artifact — diff (semantic breaking changes), graph (transitive blast radius), enforce (recursive policy, fail-closed) and verify (the same artifact at design-time via the CLI and at runtime via the operator) — while making zero deployment decisions.
| Versioned artifact | Semantic diff | Dependency graph | Transitive policy | Runtime verify | Orchestrator-agnostic | Deploys? | |
|---|---|---|---|---|---|---|---|
| Score (score.dev) | — | — | — | — | — | ✅ | No |
| Crossplane Configuration | ✅ | — | Partial | — | Partial | — | Yes |
| KubeVela / OAM | — | Partial | Partial | — | Partial | Partial | Yes |
| Radius | — | — | ✅ | — | — | Partial | Yes |
| Kratix | Partial | — | Partial | — | — | Partial | Yes |
| Backstage / Port | — | — | Partial | — | — | ✅ | No |
| Kargo | ✅ | — | — | — | Partial | — | No |
| Pacto | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | No |
✅ first-class · Partial adjacent or limited · — not in scope. Verified against each project's own documentation, August 2026; these projects move fast, so re-check the cells before relying on them. How to read the columns:
- Versioned artifact — the unit is immutably versioned and pinnable by digest
- Semantic diff — changes are classified by compatibility impact rather than rendered as text; a line-based diff is Partial
- Dependency graph — a service-to-service graph traversed transitively, with downstream blast radius; package-level resolution or ordering inside one application is Partial
- Transitive policy — governance rules evaluated across the dependency closure, fail-closed
- Runtime verify — running workloads checked against an independently declared contract; reconciling toward the tool's own desired state is Partial
- Orchestrator-agnostic — ✅ means the tool needs no Kubernetes control plane of its own. This is the softest column: between ✅ and —, Partial is a judgement of degree
- Deploys? — whether getting workloads running is part of the product's own job, even when a GitOps agent performs the apply. Kargo scores No on its own documentation: "Promotions are different from deployments … The job of deploying … is left to a GitOps agent like Argo CD"
Several of these are complementary rather than competing: a contract can gate a Kargo promotion, feed a Backstage card or front a Crossplane provisioner. The point is the combination. Other rows do one or two of these well — Radius computes a transitive application graph, Crossplane resolves package dependencies through a Lock CRD, KubeVela re-checks applied resources for configuration drift, Kargo verifies Freight before promoting it — but Pacto is the only row where one versioned artifact is diffed for breaking changes, resolved into a service graph with blast radius, gated by recursive fail-closed policy and verified against what is actually running, with no control plane of its own and no deployment decisions.
What Pacto is NOT:
- Not a deployment tool — it describes services, not how to run them, and makes zero deployment decisions, which keeps it complementary to deploy engines like KubeVela, Radius and Kratix rather than competing with them
- Not a service mesh — no sidecars, no traffic interception
- Not a service catalog or portal — the dashboard renders ownership, SBOM and readiness from contracts and runtime; it feeds Backstage/Port, it doesn't replace them
- Not another configuration language — it composes the schemas you already own
See MANIFEST.md for the full rationale.
# Installer script
curl -fsSL https://raw.githubusercontent.com/TrianaLab/pacto/main/scripts/get-pacto.sh | bash
# Go
go install github.com/trianalab/pacto/v3/cmd/pacto@latest
# From source
git clone https://github.com/TrianaLab/pacto.git && cd pacto && make buildThe installer script also installs the two official plugins and leaves a
version-stamped binary that pacto update can upgrade in place. go install
and make build install pacto alone into $GOBIN, and a go install build
reports its version as dev because the stamp is applied at release time. The
Installation guide covers pinning a
version, installing without sudo and uninstalling.
Full documentation at pacto.run.
| Guide | Description |
|---|---|
| Quickstart | From zero to a published contract in about 5 minutes |
| Contract Reference | Every field, validation rule and change classification |
| For Developers | Write and maintain contracts alongside your code |
| For Platform Engineers | Consume contracts for deployment, policies and graphs |
| CLI Reference | All commands, flags and output formats |
| Dashboard | Deploy the dashboard container alongside the operator |
| Kubernetes Operator | Runtime contract tracking and verification |
| MCP Integration | Connect AI tools (Claude, Cursor, Copilot) to Pacto via MCP |
| Plugin Development | Build plugins to generate artifacts from contracts |
| Examples | PostgreSQL, Redis, RabbitMQ, NGINX, gRPC and more |