Appearance
CLI Commands
Reference for the keel CLI. Access levels are admin > developer > viewer. The badges describe the IAM-role path. When you sign in as an operator, the control plane checks the command's capability grant instead. Commands without a badge may still require AWS credentials or an operator grant.
Global flags
Available on every command:
| Flag | Type | Default | Description |
|---|---|---|---|
--region | string | — | AWS region override |
-v, --verbose | bool | false | Enable debug logging |
--config | string | ./keel.yml | Config file path |
--env | string | — | Target environment (overrides KEEL_ENV and the active environment) |
--no-color | bool | false | Disable color output |
--cautious | bool | false | Preview and confirm every action before changing AWS state |
Core
keel init
Initialize a new Keel project by creating a keel.yml in the current directory. Interactive: app name (default: directory name), region (default us-east-1), service port (default 8080), networking and load-balancer choices, pipeline source (default github) and repository. Errors if the config file already exists.
Keel also writes an annotated keel.yml.example with every supported option. It does not overwrite an existing example or read it as configuration.
keel up admin
Provision all infrastructure defined in keel.yml. Generates OpenTofu configuration and runs plan + apply to create the VPC, ECS cluster, ALB, ECR repositories, sites, schedules, and any add-on services. Registers the app+environment in the DynamoDB registry and (when Keel manages the CodeCommit repo) adds a git remote named keel.
New services start at zero tasks until the first image is built. keel up offers to run the initial deployment; use --deploy -y to run it without prompts.
keel deploy [service-or-site] developer
Deploy one service or site, or the entire application. Keel runs git preflight checks, builds with CodeBuild or --local, registers service task definitions, runs the release command, promotes services, and then publishes sites. Sites-only deployments skip container build phases; local site builds also skip git preflight. See build_in.
| Flag | Default | Description |
|---|---|---|
--watch | false | Stay attached and stream deployment progress |
--local | false | Build locally instead of using CodeBuild |
--lock-timeout | 30 | Deploy lock timeout in minutes |
--force | false | Override an existing deploy lock |
--skip-release | false | Skip the release command for this deploy |
--release-timeout | — | Override release.timeout for this deploy (e.g. 20m) |
--allow-dirty | false | Deploy with uncommitted changes in the working tree |
-y, --yes | false | Accept every preflight warning without prompting |
--no-push | false | Never push to the Keel-managed source repository |
The release timeout must fit inside --lock-timeout.
keel deploy reconcile developer
Inspect incomplete deployment records against live AWS state. For each record, Keel can resume it, mark it succeeded or failed, or skip it, then release any stale deploy lock.
keel rollback [service] developer
Point a service to a previous task-definition revision without rebuilding or rerunning the release command.
| Flag | Default | Description |
|---|---|---|
--to | 0 | Roll back to a specific task definition revision (default: the previous one) |
--watch | false | Stay attached and stream rollback progress |
--lock-timeout | 30 | Deploy lock timeout in minutes |
--force | false | Override an existing deploy lock |
Refuses to roll back to a revision whose image has been expired from ECR.
keel status
Show the current status of all ECS services: running task count, health, last deployment time, and CPU/memory utilization.
keel ps
List running tasks with task ID, availability zone, revision, uptime, health, CPU, and memory. Per-task metrics can reveal uneven load hidden by service averages. Missing metrics appear as —. Flags: --json, --service.
keel cost
Estimate the monthly cost of what keel.yml describes — the provisioned baseline, priced from config alone with no AWS credentials. Usage-driven costs are listed with their rates; override assumptions with flags (--deploys 10, --build-minutes 4, --job-minutes 5, --nat-gb, --log-gb, --transfer-gb, --site-gb, --site-requests, --site-build-mb, --image-gb 5). --all covers every environment; --json for machines. See Cost Estimates & Budgets.
cost budgetadmin — create/update an AWS Budget filtered by this environment's tags.--email(required, repeatable),--limit(default: derived from the estimate),--threshold(default80,100),--headroom(default40),--removecost budget-show— the limit, actual spend, forecast, and alert thresholds
keel history
Show the deployment history for this application environment. --limit (default 20) caps the number of entries. The history is Keel's own record of what it deployed — not a view of AWS: a service updated outside Keel leaves no entry, and entries survive the environment they describe being torn down.
keel history prune admin
Permanently delete deployment history for this app and environment. Keel confirms with the record count; -y, --yes skips the prompt. keel destroy keeps history unless you pass --prune-history.
keel rescue admin
Diagnose an interrupted operation by reporting the state lock and resources absent from OpenTofu state. Repairs require explicit flags. Keel prints deletion commands for untracked resources but does not run them. See Interruptions & Rescue.
| Flag | Default | Description |
|---|---|---|
--unlock | false | Release the state lock (only when nothing holds it; always confirms) |
--converge | false | Re-run the apply to finish an interrupted keel up |
--finish-destroy | false | Re-run the teardown to finish an interrupted keel destroy |
--delete-retained | false | With --finish-destroy, delete retain: true resources instead of leaving them |
--converge and --finish-destroy together is an error. Within one run the order is: report → unlock → converge/finish-destroy.
keel plan
Preview all infrastructure changes that will be applied on the next keel up.
keel dashboard
Launch the interactive TUI dashboard for the selected environment. Live ECS/RDS/ElastiCache/ALB/CloudWatch/SSM state; actions are gated by your access level or operator grants inside the TUI. --direct bypasses the control plane for an IAM session. See The Dashboard.
keel destroy admin
Tear down all infrastructure Keel provisioned for this application. Resources declared retain: true are left running in AWS and released from Keel's state; the database is deleted after a final snapshot unless --no-final-snapshot. Confirmation requires typing the app name.
| Flag | Default | Description |
|---|---|---|
--force | false | Skip confirmation prompt |
--delete-retained | false | Delete resources declared retain: true instead of leaving them in AWS |
--no-final-snapshot | false | Delete the database without taking a final snapshot |
--prune-history | false | Also delete this environment's deployment history (irreversible) |
A successful destroy also releases the deploy lock if one was held, and reports how many deployment records were kept. An interrupted destroy points at keel rescue.
keel apps
List all Keel applications registered in the DynamoDB app registry for the current AWS account. The registry is created by the first keel up.
keel version
Print the version, commit hash, and build date of the Keel binary.
keel license and keel licenses
keel license reports the active edition, expiry, source, and every gated capability (--json). keel licenses prints Keel's Apache-2.0 licence; --third-party prints attribution for every module linked into the binary.
keel orphans
List AWS resources tagged as Keel-managed that no current keel.yml declares, with their estimated cost (--json).
Runtime operations
keel logs [service]
Stream or tail CloudWatch logs for one service (default: the first service in keel.yml).
| Flag | Default | Description |
|---|---|---|
-f, --follow | false | Stream logs in real time |
--since | 10m | How far back to fetch logs (e.g. 10m, 1h, 2d) |
--filter | — | CloudWatch Logs filter pattern |
keel exec [service] developer
Open an interactive shell or run a command inside a running container via ECS Exec. -c, --command defaults to /bin/sh; --reason is recorded beside the transcript when session audit is enabled.
Keel speaks the SSM session protocol itself, so the normal path needs neither the AWS CLI nor session-manager-plugin. --legacy-session (or KEEL_LEGACY_SESSION=1) uses those external tools as an escape hatch.
keel run -- <command>... developer
Run a one-off command — a migration, a backfill, a console — as a new ECS task using a service's task definition, IAM role, security group, and environment.
| Flag | Default | Description |
|---|---|---|
-s, --service | release service | Service whose task definition and role to use |
-i, --interactive | false | Attach a terminal, for a console or a REPL |
--timeout | 1h | Give up and stop the task after this long |
--cpu | — | Task CPU units for this run (e.g. 1024) |
--memory | — | Task memory in MiB for this run (e.g. 2048) |
Interactive run -i still needs the AWS CLI and session-manager-plugin; unlike keel exec, it attaches to a newly launched task through the legacy external session path.
keel scale <service> <count> developer
Set the ECS desired task count for a service. Scheduled tasks are not supported because EventBridge starts one task per event.
keel autoscale
autoscale show [service]— what scales each service, configured and live, with drift called out (--json). A difference usually means an apply is pending, so both halves are reported.autoscale set <service>admin — write autoscaling tokeel.yml; only the flags you pass change. Flags:--min,--max,--cpu,--memory,--requests,--queue,--backlog-per-task, cooldowns, and matching--no-*flags. A queue target is required formin: 0. Nothing changes in AWS untilkeel up— OpenTofu owns the scalable target.autoscale off <service>admin — remove the service's autoscaling block
keel jobs
jobs list [service]— scheduled tasks: what's declared, what's live in EventBridge Scheduler, and when each next fires (computed locally — Scheduler doesn't report it). Drift, including a schedule pinned to a stale revision, is called out (--json)jobs run <service>developer — run one firing now, using the schedule's own task definition, network config, and security group; the schedule itself is untouched (--timeout, default15m)
keel sites
sites list [site]— configured vs live state per site: bucket, where it builds, object count, size, URL (--json). A provisioned-but-never-deployed site serves a 403, and the listing says sosites deploy [site]developer — build the site wherebuild_insays (printed before it starts), publish it, and invalidate the CDN with a single/*path. In CodeBuild the build clones the commit and uploads the files itself; locally it uploads changed files (compared by content hash) and deletes removed ones. Flags:--local,--skip-build,--no-delete,--dry-runsites verify <site>admin — fordomain.dns: external: read the us-east-1 certificate from ACM and recordcdn.certificate_issuedinkeel.ymlso the next apply can attach the alias
Services & environments
keel services
services list— list configured services with type and statusservices add <type>— add adatabaseorcacheadd-on tokeel.yml(runkeel upafter)services remove <type>— remove an add-on service
keel env
env list— list environments, regions, accounts, and the active oneenv use <environment>— persist the active environment for this app under~/.keelenv current— show the environment the current context targetsenv add <environment>— declare a new environment inkeel.ymlwhile preserving comments. Flags:--env-region(defaults to the app region) and--account(enables account isolation). Adding the first named environment also writes the existing implicitdefaultenvironment. Runkeel up --env <name>to provision it.
keel db
Inspect the managed database. The master password is generated and rotated by AWS and stored in Secrets Manager; Keel never holds a copy. See Database Credentials.
db credentials(aliascreds) admin — host, port, database, username, and the password masked;--showprints itdb urladmin — one-line admin connection string (postgresql://...ormysql://...), e.g.psql "$(keel db url)"db shell(aliasespsql,mysql) admin — open a local database client through a Keel tunnel; the password is passed through the process environment rather than its argument listdb grant <iam-user>/db revoke <iam-user>admin — create or drop a per-person database role whendatabase.iam_authis enabled (Pro)db logs— tail database engine logs from CloudWatch. Requiresdatabase.log_exportsinkeel.yml; Keel reports the missing setting when exports are disabled. Flags:-f/--follow,--since 10m,--filter,--typedb resize <instance-class>admin — write the new size tokeel.yml, then review withkeel plan. Never calls the AWS API directly (OpenTofu owns the size); the output names the consequences — RDS restarts the instance, single-AZ means downtime, multi-AZ fails over
keel cache
cache resize <node-type>admin — same contract asdb resize; ElastiCache replaces the nodes, and cached data is lost unless a replica can fail over
The database lives in private subnets, so db shell and third-party clients use keel tunnel @database. Keel ships no database client; install psql or mysql locally.
Config variables & settings
keel config
Values are stored in SSM Parameter Store as SecureStrings at /keel/<app>/<env>/<key> and injected into ECS task definitions.
config set KEY=VALUE [KEY=VALUE ...]config get KEYconfig list— names/type/version only; values never printed. Also lists the AWS-managed block (e.g.@database credentialsand theDATABASE_*variables it injects) so the full set of variables your containers see is in one place.config unset KEY [KEY ...]
Managed variable names (DATABASE_USER, DATABASE_PASSWORD, DATABASE_CREDENTIALS) are refused by set/get/unset — they come from a secret AWS generates and rotates; read them with keel db credentials.
keel settings
Project-level CLI behavior, persisted in keel.yml and shared across environments.
settings/settings list— show all settingssettings get <setting>— print one valuesettings set <setting> <true|false>— change and persist (verbose,cautious)
Resources & access
keel resources
Summarize built-in (@vpc, @cluster, @registry, @load-balancer, @logs, @pipeline, @database, @cache, @domain, @waf), managed, and linked resources with bindings, IAM capabilities, network rules, and ownership. Flags: --service, --managed, --existing, --json.
resources show <name>— effective bindings and rules for one resource (--json)resources add <type> <name>— declare a manageds3,sns, orsqsresource. Flags:--bind SERVICE:CAP[,CAP](repeatable),--versioning,--fifo,--visibility-timeout(default30),--retain(defaulttrue)resources link <arn-or-identifier>— link an existing resource. Flags:--as(required),--type,--url,--endpoint,--port,--security-group,--secret-arn,--secret-env,--kms-key-arn,--bindresources bind <resource> <service>— grant capabilities. Flags:--access(required, comma-separated),--prefix(S3),--envresources unbind <resource> <service>resources remove <name>— refuses while bound (--force) or protected byretain: true
keel resources status
The live state of the managed database, cache, and load balancer, with metrics — the terminal view of the dashboard's Resources tab, including topology (read replicas, Aurora cluster members, cache replicas). A declared resource that doesn't exist in AWS reports NOT DEPLOYED rather than being omitted. --json.
keel access
access show <service>— the service's task role, security group, bindings, add-ons, and custom IAM (--json)access explain <service> <resource>— why a service can access a resource
Domains & WAF
keel domains
A domain needs a zone, a certificate, and records; domain.dns records who owns the zone (route53 | route53-managed | external) and decides how much Keel does for you. See Custom Domains.
domains add <domain>admin — writeskeel.yml(scoped to the environment) and nothing else; runkeel upafter. Looks the zone up once and records the mode; a zone that doesn't exist requires you to choose--dns route53-managedor--dns external. Flags:--zone,--zone-id,--dns,--alias(repeatable),--certificate-arn,--no-force-httpsdomains remove <domain>admin — removes it fromkeel.yml; the nextkeel updestroys the certificate and alias records. A hosted zone Keel created is never destroyed (recreating one invalidates the registrar delegation)domains status(aliaslist) — the live state: zone, delegation checked with a real DNS query (Route 53 reports a healthy zone even when the registrar points elsewhere), certificate, and the single next thing to do (--json)domains records— every record someone still has to create, in provider-form shape; empty means nothing left (--json)domains verifyadmin — recheck end to end and, fordns: external, record an issued certificate inkeel.ymlso the next apply attaches the HTTPS listener.--waitpolls (--timeout 15m)
keel waf
waf enableadmin — default rule setAWSManagedRulesCommonRuleSet;--rulesfor a comma-separated listwaf disableadminwaf status
Infrastructure
keel infra
infra planadmin — preview infrastructure changes;--jsonemits OpenTofu's JSON plan schema on stdout.--keep-planleaves the saved plan in place so the next apply is bound to it (by default the plan file is discarded when the command ends — it embeds a state snapshot including sensitive values).infra applyadmin — apply pending changes and converge ECS services against the resulting infrastructure. When a saved plan exists (frominfra plan --keep-plan), the change set that runs is exactly the one that was displayed; otherwise a fresh apply.infra output— show outputs from the last apply (ALB DNS name, ECR URLs, VPC IDs)infra history— applies and destroys, including failed or interrupted operations, with actor, commit, plan summary, and resulting state (--limit,--json)infra history pruneadmin — permanently remove this environment's apply history (-y)infra unlock <LOCK_ID>admin — release a stale OpenTofu state lock left by an interrupted operation.LOCK_IDis the "ID:" field of the "Error acquiring the state lock" message. Confirms first;--yesfor scripts. Only break a lock nobody holds. (keel rescuefinds the lock ID and holder for you — see Interruptions & Rescue.)
Control plane and audit
keel api
api deployadmin — create or update the account-level control-plane Lambda, Function URL, roles, and cacheapi status— report what is deployed and whether this client can reach it (--json)api whoami— ARN, role, level, authorization path, operator label, and stable principal established by the serverapi destroyadmin — remove the control plane; direct IAM operation continues
keel audit
audit decisions— authorization decisions from the last seven days by default. Flags:--outcome allowed|denied,--who,--since-hours, and--allto include routine readsaudit sessions— recorded interactive sessions in this environmentaudit transcript <stream>— print one recorded session
Decision reads use the account-scoped audit capability. Session listings and transcripts use the environment-scoped transcript capability. See Audit Records.
Operators and grants
keel auth idp
idp setup— create the account-level operator Cognito pool, identity pool, hosted sign-in page, and federated role (--hosted-ui-prefix; elevated key)idp status— show what is provisionedidp add <email>/idp remove <email>— begin or end an enrollment; removal also drops the principal's grantsidp suspend <email>/idp restore <email>— disable and restore access without changing grantsidp list— enrolled operators with principal and provider subjectidp export— print the one account-wide sign-in token (--jsonfor the provider document)idp login— browser sign-in (--tokenfor first use, or--providerfor the scriptable file form)idp logout— remove local authentication while remembering the provider;--forgetremoves bothidp destroy— remove the operator identity provider (--force; elevated key)
keel auth grants
grants list— your rows, or the whole grid for an administrator (--json)grants allow <operator> <capability>/deny— write a row scoped with--app,--env, or--platform;--reasonrecords whygrants revoke <operator> <capability>— remove a row
An operator may be named by email or stable prn_… principal. See Operators for capability kinds and precedence.
Shared platforms and previews
keel platform
platform init, up, show, list, set, export, apply -f, lock, and destroy manage one shared VPC and ECS cluster. An EC2 fleet is configured with keys such as capacity.ec2.instance_types; the same cluster may host Fargate and the fleet. destroy refuses while tenants remain, even with --force.
keel preview
preview name, create, list, destroy, and reap manage branch-named environments synthesized from preview:. Pull-request numbers are optional metadata rather than names. Creation/listing require Pro; teardown remains available regardless of license state.
Auth & teams
keel auth
auth login— start a session, prompting for an MFA code.--mfa-serialoverrides device discovery. Sessions last 8 hours and are not auto-renewed.auth logout— clear the cached session;--purgealso removes the stored access keyauth setup— guided one-time setup: creates the three roles, your Keel admin user, and its MFA device.--dry-runprints every policy document without touching AWS;--forceskips confirmation. Needs elevated AWS credentials, held in memory only.auth whoami— current identity, account, role, access level, and credential expiryauth join— configure auth from an admin-issued access key.--account(required),--role(expectation only; IAM decides)auth connect github <organization>admin — create the CodeConnections connection CodeBuild uses to clone from GitHub, register the account source credential, print the console authorization URL, and wait (--timeout, default15m). Follow Connecting GitHub, especially the required App Installation selection.
keel auth mfa
mfa enroll— register an authenticator app against your Keel IAM user; the secret never leaves your machinemfa statusadmin — enforcement per role and enrollment per membermfa openadmin — grant enrollment rights to existing members when migrating a team to MFA (--force)mfa enforceadmin — require MFA to assume any Keel role (--disableto remove,--forceto skip confirmation)
keel auth team
team listviewer — list members (--allincludes disabled)team add <email> <role>admin — provision a member's IAM user and access key, pending MFA enrollment (--no-userfor SSO-managed accounts,--force)team activate <email>admin — grant access once they have enrolled exactly one MFA deviceteam reenroll <email>admin — reset a lost MFA device and reissue their key (--keep-key,--force)team remove <email>admin — revoke access, delete their access keys and IAM user (--purge,--force,--allow-self)team set <email> <role>admin — change a member's role, re-scoping their IAM user
Diagnostics
keel debug
debug logs— recent diagnostic log entries (-nlines, default50;-f, --follow;--all)debug path— print the log file path (~/.keel/logs/keel.log)debug info— version, platform, and log diagnostics for bug reports