reimagined.
Same providers, same plan/apply loop. Rebuilt for scale, speed, security and discoverability. Keep scrolling.
12 minutes · no account · no cloud
- State per resource
- Sealed and signed
- Same providers
package estate
import loc "pravo.dev/providers/hashicorp/local"
$local: loc.#Provider
#Service: {
name: string
port: int & >=1024 & <=65535
file: $local.#Resource.local_file & {
filename: "\(name).env"
content: "PORT=\(port)\n"
}
}
api: #Service & {name: "api", port: 8080, file: file_permission: "0600"}
web: #Service & {name: "web", port: 8081}
pravo will perform the following actions:
# api.file (local_file) will be created
+ api: file: {
...
+ file_permission: "0600"
+ filename: "api.env"
...
Plan: 2 to add, 0 to change, 0 to destroy.
Graph: planned 2
One definition, two instances and the plan for both. The file and the output were recorded from pravo 0.1.0-dev with cue v0.17.1.
Rebuilt for teams
Multiplayer by design.
The classic tools shine on a laptop. In multiplayer scenarios they break: one state file that every plan reads in full, no record of who changed what. An entire ecosystem of external tools had to cover those gaps. pravo learns from the past but starts from a clean slate, with multiplayer mode built in.
The whole estate in a browser
One command, pravo serve, opens a read-only viewer on your machine. The graph, plans, history, state, secrets, policies, templates and traces are in one place. There is nothing to host and nothing to set up.
Change one resource, read one resource
A plan reads only what the change reaches, so its cost follows the change and not the size of the estate. Applies that do not overlap run at the same time, started by different people.
How plans stay small Trust itSealed and signed state
State is encrypted to a list of readers and every change is signed. A copy of the bucket shows nothing, and a record that was altered shows up. Readers, writers and admins have different keys, and the secrets a team shares live in the state with a history of who set each.
Signatures and roles Take over what existsFind what nothing manages
Most estates were built before the code. pravo discover lists what exists in a scope and sets it against the state, and adopt writes the resource that brings an object under management.
Plans and applies
Change one resource. Read one resource.
OpenTofu reads every resource on every plan. pravo starts at your change, follows the recorded dependencies, and reads only what the change reaches.
Change one value in an estate of 2001 resources, then run a plan. How many resources does each tool read from the cloud?
OpenTofu reads
- of 2001 resources
- 2001
pravo reads
- of 2001 resources
- 1
Both plans propose the same change; pravo ran with default settings. How reads are counted.
Why it matters
Reads follow the change
A plan starts at your change and follows the recorded dependencies. It reads what the change reaches, and the apply locks and writes only that. The requests it sends to your cloud depend on the change, not on the size of the estate. Drift in a resource it does not reach is found by pravo drift or by a plan that does.
A budget for staleness
Each record remembers when it was last read from the cloud. The refresh age sets how stale it may be before a plan reads it again, and a scheduled pravo drift --due reads the most overdue records, up to a limit you set.
Split by ownership, not by size
An estate can grow without its requests to the cloud growing with it, so there is no need to split a state to keep it fast. Split it where ownership, permissions or blast radius divide. Applies to different resources run at the same time; an overlapping apply is refused, not queued.
When to split a stateSee it
Understand your infrastructure at a glance.
pravo serve opens a read-only viewer on your machine. These pages come from a sealed state with three members, a stored plan, two policies and four recorded runs.

1
2
01 Graph
Everything you manage, in one map. Every resource and what depends on what. Open a group, follow a wire, jump to the code behind a resource.
- Open a group
- Follow a wire

1
2
02 Plan
What a plan changes. Lay a saved plan over the graph and read each change before anyone applies it.
- The resource marked for replacement
- The old and the new content, line by line

1
2
03 Policies
Rules that are written down. Policies are versioned and signed, and each apply names the versions that judged it. The studio tries a rule on a plan first.
- Who signed it
- The rule itself, in CUE

1
2
04 State
Who can do what. Members, roles and a check that every record was written by someone allowed to write it.
- The check, all clear
- Members and their roles

1
2
05 Traces
Where the time went. Every run records its spans, and pravo captures the network requests a provider makes while it works. They appear in the viewer with nothing to set up, or you can send them to your own collector.
- Network requests captured from the provider
- A provider call
Self-service
Self-service that stays code.
A platform team writes a pattern once, as a definition. Anyone with a checkout fills in its form in the viewer and gets the code of a new instance. One person prepares the plan with a reader key, and someone with a writer key applies it.
The definition is the form
The types, defaults, comments and constraints of the fields become the form. There is no second schema to keep in step.
02 · The checksChecked before it is pasted
The viewer loads the specification with the new code in memory and tries every policy in force. The plan judges it again.
03 · The instancesInstances follow their template
An instance is worked out from its template, not copied. Change the template, and the next plan changes every instance.
package estate
import "pravo.dev/pravo"
#Service: pravo.#Template & {
$template: {
name: "service"
title: "Web service"
description: "A service with a generated secret and a rendered config file."
inputs: {
name: {}
owner: {label: "Owning team", description: "The team that gets paged for it. It starts with team-."}
env: {}
port: {}
}
}
// Lowercase letters, digits and dashes. It names the config file.
name: string & =~"^[a-z][a-z0-9-]{2,30}$"
// The team that answers for the service.
owner: string & =~"^team-"
// Where it runs.
env: *"dev" | "staging" | "prod"
// The port it listens on.
port: *8080 | int & >1024 & <65536
secret: $random.#Resource.random_password & {length: 24}
config: $local.#Resource.local_file & {
filename: "out/\(name).env"
content: "OWNER=\(owner)\nENV=\(env)\nPORT=\(port)\n"
}
}


pravo will perform the following actions:
# services.checkout.secret (random_password) will be created
+ services: checkout: secret: {
...
+ special: true
...
# services.checkout.config (local_file) will be created
+ services: checkout: config: {
+ content: "OWNER=team-checkout\nENV=prod\nPORT=8080\n"
...
+ filename: "out/checkout.env"
...
Plan: 2 to add, 0 to change, 0 to destroy.
Graph: planned 2 · skipped 4 · not read 4
Policies: 1 satisfied.
The template, the form that the viewer builds from it, and the plan of the code it gave, made by a reader. Recorded from pravo 0.1.0-dev with cue v0.17.1.
Take it for a spin
Run it, bring your own stack, or learn CUE first.
pravo is experimental and tested end to end. Try it and decide for yourself.
Download
Download pravoOr install from a terminal
Binaries for macOS, Linux and Windows are on the releases page.
Other systems
Run a plan
Install pravo, write one file, plan it, apply it, change it and destroy it. 12 minutes, with no cloud account.
Quick start Bring your ownTry your OpenTofu or Terraform stack
Translate the HCL, convert the state file and plan until the plan is empty. Every step before your first apply leaves your infrastructure and your OpenTofu state as they are.
Migrate Learn firstNew to CUE
CUE from zero in 14 lessons and 136 minutes. Then pravo in 10 lessons and 136 minutes. CUE is a general configuration language, so the first track is useful beyond pravo.
LearnUsing an agent? Install the pravo skill, so that it writes CUE and not HCL.
About
Why I built this.
I'm Marcin Wyszynski. I co-founded Spacelift and OpenTofu, and I had been exploring CUE for a while. Ten years of running Terraform and OpenTofu left me with notes on what I would do differently, and one day I decided to throw some tokens at the problem and see what gives.
pravo is the result. The notes are mine, and the code was written with Claude from them. It is experimental: it drives real OpenTofu providers and its behaviour is documented and tested. It is released under Apache 2.0 for anyone to use, change and build on. Take it for a spin and tell me what you found.