Skip to content

plan

Show a diff of what will be created, updated, replaced, or destroyed. The plan compares your config against the current state file.

Terminal window
kyku plan [options]
Flag Default Description
-e, --env <environment> default Environment workspace
-c, --config <path> ./infrastructure.ts Path to config file
-p, --passphrase <phrase> Passphrase for encrypted state
--out <path> Save plan to a file for later application
--json false Print the redacted plan as JSON (same change set as the human renderer)
--prefix <p> Opt-in deploy prefix for new cloud names
--detailed-exitcode false 0 no changes, 1 error, 2 changes (CI drift gate). Validation also exits 1 when this flag is set. Honored together with --json.
--target <selector> Plan matching resources and their dependency ancestors. Repeatable. Selector is an exact id, an id glob (vm-*), or tags.key=value on resource.tags.
--exclude <selector> Omit matching resources. Errors if anything left in the graph still depends on them. Same selector forms as --target.
--migrate-state false Upload local .kyku state to the configured remote backend, then plan from remote. Refuses if remote state already exists.
--force-migrate false Same as --migrate-state but overwrites remote state if it exists.
Terminal window
# Preview changes for default environment
kyku plan
# Preview changes for production
kyku plan --env=prod
# Save plan to a file
kyku plan --out plan.json
# Machine-readable plan (secrets redacted)
kyku plan --json
kyku plan --json --detailed-exitcode
# Load config from a custom path
kyku plan --config=./staging.ts
# Fail CI when the plan is not a no-op
kyku plan --detailed-exitcode
# exit 0 = clean, 2 = drift, 1 = error
# Plan a leaf and the resources it depends on
kyku plan --target vm-web
# Plan every id matching a glob (each match still pulls in ancestors)
kyku plan --target 'vm-*'
# Plan resources tagged env=prod on resource.tags (not provider labels)
kyku plan --target tags.env=prod
# Skip a resource (fails if something else still depends on it)
kyku plan --exclude bucket-old
# Show what would change without a passphrase (secrets shown as [encrypted])
kyku plan
# Opt-in: upload local state to the remote backend, then plan from remote
kyku plan --migrate-state
kyku plan --force-migrate
Plan: 3 to create, 1 to update, 0 to replace, 1 to destroy
+ Vpc (vpc-main)
region: "us-east"
cidr: "10.0.0.0/16"
+ SecurityGroup (sg-web)
ingress: [...]
+ Vm (vm-web)
image: "ubuntu-22.04"
instanceType: "small"
- SecurityGroup (sg-old)
(removed from config)
~ Vm (vm-existing)
instanceType: "small" → "medium"

Use --out to serialize the plan to JSON for review or later application. --json prints the same redacted document to stdout.

Saved plans embed stateSerial, stateLineage, and a configHash of the desired graph. kyku apply --plan refuses the file if the state serial no longer matches or the config has changed. Re-run kyku plan, or pass --force-stale-plan.

Terminal window
kyku plan --out plan.json
kyku apply --plan plan.json

Sensitive property values are stored as sensitive:<hash> placeholders, never in plaintext.

--target / --exclude accept an exact resource id, an id glob (* / ?, not a regex), or tags.key=value against resource.tags only (not provider labels, not name). A selector that matches nothing is an error. --target always includes ancestors (the dependency closure). A targeted --out file records the selector strings in targets so kyku apply --plan cannot treat a partial plan as a full one. Resources left out print a drift warning on stderr. kyku destroy --target uses the same selectors but expands dependents instead of ancestors.