Appearance
Architecture
Keel is a single Go binary that combines infrastructure-as-code with direct SDK calls.
keel.yml
|
+------+------+
| |
Infrastructure Runtime Ops
| |
+------+------+ +------+------+
| | | | |
HCL Gen OpenTofu ECS ECR CloudWatch
| | SDK SDK SDK
.tf files S3 State
| DynamoDB
Plan/Apply LockTwo planes
Infrastructure provisioning (keel up, keel infra plan/apply) flows through OpenTofu. Keel generates HCL from your config, writes .tf files, and shells out to the tofu binary with an S3 backend and DynamoDB state locking. State is keyed per environment (<app>/<env>/terraform.tfstate). Credentials are passed to the subprocess via environment variables, never written to disk.
Runtime operations (keel deploy, keel logs, keel exec, keel scale) go directly through the AWS SDK — no Terraform round-trip. A deploy doesn't re-plan your VPC; it builds an image, registers a task definition, and updates a service.
The app registry
A DynamoDB table tracks all Keel app+environments across the account, so any team member can run keel apps to discover deployed applications, regardless of which machine ran keel up.
Internal layout
For contributors, the codebase splits along the same lines:
| Package | Responsibility |
|---|---|
internal/cli | Cobra commands — thin glue that delegates to domain packages |
internal/config | keel.yml parsing, validation, defaults, environment merging |
internal/auth | Access levels, credential caching, IAM bootstrap, team management |
internal/aws | AWS SDK v2 wrappers (ECS, ECR, CloudWatch, SSM, STS) |
internal/infra | OpenTofu orchestration and HCL generation |
internal/deploy | Docker/CodeBuild builds, ECS deploys, release commands, rollback |
internal/project | Workspace detection and the DynamoDB app registry |
internal/tui | The Bubbletea dashboard |
internal/util | Logging, error types, terminal detection |
Access control
Every privileged command declares the access level it requires (viewer, developer, or admin) and checks it before doing anything. The same levels gate actions in the dashboard, and the command palette annotates each command with the level it needs. See The Auth Model for how the levels map to IAM roles.