Open-source infrastructure-as-code engine. Drop-in alternative to Terraform and OpenTofu.
Documentation | Quick Start | Blast Radius | Resource History | Observability
Oxid reads your existing .tf files, talks directly to AWS/GCP/Azure providers via gRPC, and stores state in SQLite or PostgreSQL. No Terraform or OpenTofu binary required.
curl -fsSL https://raw.githubusercontent.com/ops0-ai/oxid/main/install.sh | bash| Terraform / OpenTofu | Oxid | |
|---|---|---|
| Execution Model | Wave-based (batch) | Event-driven per-resource |
| Parallelism | Resources in same wave wait for slowest | Dependents start instantly when deps complete |
| State Backend | JSON file or remote backend | SQLite (local) / PostgreSQL (teams) |
| Config Language | HCL only | HCL + YAML |
| Provider Protocol | Wraps binary / shared lib | Direct gRPC (tfplugin5/6) |
| Queryable State | terraform show |
Full SQL queries |
| Resource History | No built-in audit trail | Full change history with attribute diffs |
| Blast Radius | No native support | Forward + reverse dependency analysis with depth levels |
| Drift Detection | Manual plan comparison | Built-in oxid drift command |
| Sensitive Output Encryption | Stored as plain text in state | AES-256 encrypted at rest (pgcrypto) |
| Structured Logging | TF_LOG env var, unstructured text |
JSON log file with resource IDs, actions, timing (Datadog/Splunk/OTel ready) |
| Apply Efficiency | Re-evaluates all resources each apply | Smart apply - only touches changed resources, skips unchanged |
| License | BSL / MPL | Apache-2.0 |
cd your-terraform-project/
oxid init # download providers, import existing state
oxid plan # preview changes
oxid apply # apply infrastructureYour existing .tf files, .tfvars, and TF_VAR_* environment variables work unchanged.
Full documentation at oxid.sh/docs
See exactly what breaks before you touch anything:
$ oxid blast-radius aws_vpc.main
Severity: HIGH (32 resources, 3 levels deep)
Types: 4 aws_subnet, 3 aws_route_table, 1 aws_eks_cluster, 1 aws_eks_node_group...
Depth 1 - direct dependent (10 resources):
~ aws_internet_gateway.main
~ aws_subnet.private[0]
~ aws_security_group.eks_cluster
...
Depth 2 - transitive dependent (12 resources):
~ aws_eks_cluster.main
~ aws_nat_gateway.main[0]
...Reverse mode shows upstream dependencies:
$ oxid blast-radius aws_eks_node_group.main --why
Dependencies of aws_eks_node_group.main
14 upstream dependencies, 2 levels deepWorks with resource types too: oxid blast-radius aws_subnet
Full audit trail for every resource. Track tag changes, instance type changes, scaling events:
$ oxid history aws_vpc.main
2026-05-07T10:30:02+00:00 ~ update (2h ago)
id: vpc-0626c706762a661e9
cidr_block: 10.0.0.0/16
tags: {"env":"prod","iac":"oxid"}
changes:
~ tag "iac" = "terraform" -> "oxid"
2026-05-07T08:15:00+00:00 + create (4h ago)
id: vpc-0626c706762a661e9
cidr_block: 10.0.0.0/16
tags: {"env":"prod","iac":"terraform"}Query history with SQL:
oxid query "SELECT address, action, captured_at FROM resource_history ORDER BY captured_at DESC"Write structured logs for Datadog, Splunk, ELK, or OpenTelemetry:
oxid apply --log-file ./oxid.logEvery event includes resource address, resource ID, action, provider, and timing:
{"timestamp":"...","level":"INFO","fields":{"event":"resource.apply.complete","address":"aws_vpc.main","resource_id":"vpc-0626c706762a661e9","action":"update","provider":"hashicorp/aws","elapsed_secs":1.2}}Already using Terraform or OpenTofu? Pipe their JSON output through oxid watch to get structured logs without changing your workflow:
terraform apply -auto-approve -json | oxid watch --log-file ./tf.log
tofu apply -auto-approve -json | oxid watch --log-file ./tf.log-- Find all t3.micro instances
oxid query "SELECT address FROM resources WHERE attributes_json->>'instance_type' = 't3.micro'"
-- Resources missing tags
oxid query "SELECT address FROM resources WHERE attributes_json->'tags' = '{}'"
-- Count by resource type
oxid query "SELECT resource_type, COUNT(*) FROM resources GROUP BY resource_type"Oxid only sends changed resources to providers. Unchanged resources are skipped entirely - no provider API calls, no noise in the output:
Plan: 0 to add, 1 to change, 0 to destroy.
aws_vpc.main: Updating...
aws_vpc.main: Update complete after 0s [id=vpc-0626c706762a661e9]
Apply complete! Resources: 0 added, 1 changed, 0 destroyed. Total time: 0s.
oxid init # initialize providers and state
oxid plan # preview changes
oxid apply # apply changes
oxid destroy # tear down infrastructure
oxid state list # list managed resources
oxid state show <address> # show resource details
oxid query "SQL" # query state with SQL
oxid blast-radius <resource> # downstream impact analysis
oxid blast-radius <resource> --why # upstream dependency chain
oxid blast-radius --plan # blast radius for planned changes
oxid history <resource> # resource change audit trail
oxid drift # detect configuration drift
oxid sync # sync from Terraform remote backend
oxid output --json # show outputs (Terraform-compatible)
oxid watch # watch Terraform/OpenTofu JSON output
oxid graph # dependency graph (DOT format)
oxid validate # validate configurationexport OXID_DATABASE_URL="postgres://user:pass@host:5432/dbname"
oxid init # tables created automaticallySensitive outputs are AES-256 encrypted at rest via pgcrypto.
We welcome contributions! Here's how:
- Try it - Run
oxid planagainst your Terraform projects and report what works - Report bugs - Open an issue
- Test providers - Try AWS, GCP, Azure, Kubernetes, Cloudflare
- Submit PRs - Code contributions welcome
# Prerequisites: Rust 1.93+, protoc
git clone https://github.com/ops0-ai/oxid.git
cd oxid
cargo build --releaseApache-2.0. See LICENSE.