{"id":49153025,"url":"https://github.com/go-to-k/cdkd","last_synced_at":"2026-06-13T06:02:03.223Z","repository":{"id":352002009,"uuid":"1191203392","full_name":"go-to-k/cdkd","owner":"go-to-k","description":"Drop-in CDK CLI for existing CDK apps — faster deploys via AWS SDK instead of CloudFormation, with local emulation for Lambda, API Gateway, and ECS.","archived":false,"fork":false,"pushed_at":"2026-06-06T17:08:59.000Z","size":10394,"stargazers_count":56,"open_issues_count":2,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-06T19:07:02.781Z","etag":null,"topics":["aws","aws-cdk","aws-cloudformation","aws-sdk","awscdk","cdk","cloudformation"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/go-to-k.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":"docs/supported-features.md","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-25T02:36:28.000Z","updated_at":"2026-06-06T17:09:00.000Z","dependencies_parsed_at":null,"dependency_job_id":"0f919faa-351f-43f9-9ffd-968a10a8c341","html_url":"https://github.com/go-to-k/cdkd","commit_stats":null,"previous_names":["go-to-k/cdkd"],"tags_count":363,"template":false,"template_full_name":null,"purl":"pkg:github/go-to-k/cdkd","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-to-k%2Fcdkd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-to-k%2Fcdkd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-to-k%2Fcdkd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-to-k%2Fcdkd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/go-to-k","download_url":"https://codeload.github.com/go-to-k/cdkd/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-to-k%2Fcdkd/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34116461,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-09T02:00:06.510Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","aws-cdk","aws-cloudformation","aws-sdk","awscdk","cdk","cloudformation"],"created_at":"2026-04-22T07:03:33.930Z","updated_at":"2026-06-13T06:02:03.208Z","avatar_url":"https://github.com/go-to-k.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cdkd (CDK Direct)\n\nDrop-in CDK CLI for existing CDK apps — faster deploys via AWS SDK instead of CloudFormation, plus local emulation for Lambda, API Gateway, and ECS.\n\n- **Drop-in CDK compatible** — your existing CDK app code runs as-is.\n- **Up to 15x faster deploys than the AWS CDK CLI (CloudFormation)**\n- **Local dev for any CDK app** — invoke Lambdas, serve API Gateway routes, run ECS tasks/services directly from your CDK code. Works against both `cdkd deploy`-managed AND `cdk deploy`-managed (CloudFormation) stacks via `--from-state` / `--from-cfn-stack` — no migration, no `cdk synth → sam local` round-trip.\n\n![cdk deploy vs cdkd deploy — side-by-side, 35s recording, real AWS deploy. cdkd finishes while cdk is still creating its CloudFormation changeset.](assets/cdk-vs-cdkd.gif)\n\n**cdkd complements the AWS CDK CLI rather than replacing it.** Use cdkd in dev/test for rapid iteration and SAM-style local execution; use the AWS CDK CLI in production for full CloudFormation tooling. Install cdkd alongside an existing `cdk deploy` workflow — no migration needed, `cdkd local *` reads deployed state directly via `--from-cfn-stack`. Bidirectional migration is also supported — [import](#importing-existing-resources) into cdkd or [export](#exporting-a-stack-back-to-cloudformation) back to CloudFormation when ready.\n\n\u003e [!IMPORTANT]\n\u003e cdkd is for dev/test workflows only — early in development, not yet production-ready.\n\n## Benchmark\n\n**cdkd deploys up to 15x faster than AWS CDK (CloudFormation)** on SDK-Provider-handled stacks; the per-stack speedup widens with size and parallelism, and drops to ~1.5-3x on stacks dominated by Cloud Control API fallback resources.\n\nNumbers below are deploy-phase only (CDK app synthesis is identical between cdkd and AWS CDK — both run the same user code through `aws-cdk-lib`'s synthesizer — so synth time is excluded from the speedup calculation).\n\n### SDK Provider path — **5.5x faster** (17.0s vs 94.4s)\n\nStack: S3 Bucket, DynamoDB Table, SQS Queue, SNS Topic, SSM Parameter (5 independent resources, fully parallelized by cdkd's DAG scheduler).\n\n| | AWS CDK (CFn) | cdkd | Speedup |\n| --- | ---: | ---: | ---: |\n| Deploy | **94.4s** | **17.0s** | **5.5x** |\n\n### VPC + CloudFront + Lambda stack — **15x faster with `--no-wait`** (40s vs 599s)\n\nReal-world stack: 1 VPC (2 AZs, NAT Gateway, public + private subnets) + Lambda Function (with `VpcConfig`) + Lambda Function URL (AWS_IAM) + CloudFront Distribution (OAC, caching disabled) + SQS Queue + EventSourceMapping + Consumer Lambda.\n\n| | AWS CDK (CFn) | cdkd | cdkd `--no-wait` |\n| --- | ---: | ---: | ---: |\n| Deploy | **599s** | 197s (3.0x) | **40s (15.0x)** |\n\nThe 15x figure requires `cdkd deploy --no-wait`, which returns as soon as each Create call returns and lets AWS finish CloudFront's ~5min propagation + NAT Gateway stabilization in the background. cdkd's default scheduler already parallelizes `CloudFront::Distribution` / `Lambda::Url` / VPC Lambda with NAT Gateway propagation (pass `--no-aggressive-vpc-parallel` to opt out); on this stack the default gives ~3x. `--no-wait` adds the rest of the gap by skipping the propagation waits entirely.\n\n### Cloud Control API fallback path — **1.6x faster** (40.9s vs 64.9s)\n\nStack: SSM Document × 3 + Athena WorkGroup × 2 (no SDK provider — CC API fallback).\n\n| | AWS CDK (CFn) | cdkd | Speedup |\n| --- | ---: | ---: | ---: |\n| Deploy | **64.9s** | **40.9s** | **1.6x** |\n\nReproduce the first two with `./tests/benchmark/run-benchmark.sh all`. See [tests/benchmark/README.md](tests/benchmark/README.md) for details.\n\n## Features\n\n- **Synthesis orchestration**: CDK app subprocess execution, Cloud Assembly parsing, context provider loop\n- **Asset handling**: Self-implemented asset publisher for S3 file assets (ZIP packaging) and Docker images (ECR)\n- **Context resolution**: Self-implemented context provider loop for Vpc.fromLookup(), AZ, SSM, HostedZone, etc.\n- **Hybrid provisioning**: SDK Providers for fast direct API calls, Cloud Control API fallback for broad resource coverage\n- **Diff calculation**: Self-implemented resource/property-level diff between desired template and current state\n- **S3-based state management**: No DynamoDB required, uses S3 conditional writes for locking\n- **DAG-based parallelization**: Analyze `Ref`/`Fn::GetAtt` dependencies and execute in parallel\n- **Rollback on failure**: When a deploy errors mid-stack, cdkd rolls back the resources it just created so the stack state stays consistent (CloudFormation parity — but cdkd does this without round-tripping through CFn). Pass `cdkd deploy --no-rollback` to skip rollback and keep the partial state for Terraform-style inspection / repair. See [Rollback behavior](#rollback-behavior).\n- **`--no-wait` for async resources**: Skip the multi-minute wait on CloudFront / RDS / ElastiCache / NAT Gateway and return as soon as the create call returns (CloudFormation always blocks)\n- **VPC route DependsOn relaxation (on by default)**: Drop CDK-injected defensive `DependsOn` edges from VPC Lambdas onto private-subnet routes so `CloudFront::Distribution` and `Lambda::Url` start their ~3-min propagation in parallel with NAT Gateway stabilization (~50% faster on VPC + Lambda + CloudFront stacks). Pass `--no-aggressive-vpc-parallel` to opt out.\n- **Local execution** (`cdkd local invoke` / `start-api` / `run-task` / `start-service` / `start-alb` / `start-cloudfront` / `invoke-agentcore` / `start-agentcore`): run Lambdas, API Gateway routes, ECS tasks, long-running ECS services, CloudFront distributions, and Bedrock AgentCore Runtimes from your CDK code. All AWS Lambda runtimes, container Lambdas, REST v1 / HTTP v2 / Function URL routes, Service Connect / Cloud Map, AgentCore HTTP / MCP / A2A / AGUI / WebSocket protocols (one-shot `invoke-agentcore` and long-running warm serve via `start-agentcore`, which serves the native contract — `POST /invocations` + `GET /ping`, MCP `/mcp`, A2A `/` — plus the `/ws` bridge for HTTP / AGUI). The Docker-backed commands work for both `cdkd deploy`-managed (`--from-state`) AND `cdk deploy`-managed (`--from-cfn-stack`) stacks; `start-cloudfront` serves the viewer-request -\u003e S3 / Lambda Function URL origin -\u003e viewer-response pipeline (CloudFront-Functions + S3-only distributions run in-process with no Docker). See [Local execution](#local-execution).\n- **Bidirectional CloudFormation migration**: `cdkd import --migrate-from-cloudformation` adopts existing CFn stacks (including `cdk deploy`-managed) into cdkd state without re-creating resources; `cdkd export` hands a cdkd stack back to CloudFormation when production-ready. See [Importing](#importing-existing-resources) / [Exporting](#exporting-a-stack-back-to-cloudformation).\n\n\u003e **Note**: Resource types not covered by either SDK Providers or Cloud Control API cannot be deployed with cdkd. Deployment fails with a clear error message naming the type + a 1-click issue link.\n\n## How it works\n\n```\n┌─────────────────┐\n│  Your CDK App   │  (aws-cdk-lib)\n└────────┬────────┘\n         │\n         ▼\n┌─────────────────┐\n│ cdkd Synthesis  │  Subprocess + Cloud Assembly parser\n└────────┬────────┘\n         │\n         ▼\n┌─────────────────┐\n│ CloudFormation  │\n│   Template      │\n└────────┬────────┘\n         │\n         ▼\n┌─────────────────┐\n│ cdkd Engine     │\n│ - DAG Analysis  │  Dependency graph construction\n│ - Diff Calc     │  Compare with existing resources\n│ - Parallel Exec │  Event-driven dispatch\n└────────┬────────┘\n         │\n    ┌────┴────┐\n    ▼         ▼\n┌────────┐ ┌────────┐\n│  SDK   │ │ Cloud  │\n│Provider│ │Control │  Fallback for many\n│        │ │  API   │  additional types\n└────────┘ └────────┘\n```\n\nFor a step-by-step walkthrough of the full `cdkd deploy` pipeline (CLI\nparsing → synthesis → asset publishing → per-stack deploy), see\n[docs/architecture.md](docs/architecture.md#5-end-to-end-pipeline-walkthrough-cdkd-deploy).\n\n## Prerequisites\n\n- **Node.js** \u003e= 20.0.0\n- **AWS CDK Bootstrap**: You must run `cdk bootstrap` before using cdkd. cdkd uses CDK's bootstrap bucket (`cdk-hnb659fds-assets-*`) for asset uploads (Lambda code, Docker images). Custom bootstrap qualifiers are supported — CDK embeds the correct bucket/repo names in the asset manifest during synthesis.\n- **AWS credentials with admin-equivalent permissions** for the resources being deployed. cdkd does NOT route through CloudFormation, so CDK CLI's `cdk-hnb659fds-deploy-role-*` is NOT sufficient — see [`--role-arn`](docs/cli-reference.md).\n\n## Installation\n\n```bash\nnpm i -g @go-to-k/cdkd          # latest release\nnpm i -g @go-to-k/cdkd@0.0.2    # pin to a specific version\n```\n\nThe installed binary is `cdkd`.\n\n## Quick Start\n\n\u003e **First-time setup**: cdkd requires a one-time `cdkd bootstrap` per AWS\n\u003e account before any other command will work — it creates the S3 state\n\u003e bucket (`cdkd-state-{accountId}`) that cdkd uses to track deployed\n\u003e resources. This is separate from `cdk bootstrap` (which sets up the\n\u003e CDK asset bucket / ECR repo and is also required — see\n\u003e [Prerequisites](#prerequisites)).\n\n```bash\n# Bootstrap (creates S3 state bucket — one-time setup, once per AWS account)\ncdkd bootstrap\n\n# List stacks in the CDK app\ncdkd list\n\n# Deploy your CDK app\ncdkd deploy\n\n# Check what would change\ncdkd diff\n\n# Tear down\ncdkd destroy\n```\n\nThat's it. cdkd reads `--app` from `cdk.json` and auto-resolves the state bucket from your AWS account ID (`cdkd-state-{accountId}`). If you bootstrapped under a previous cdkd version, the legacy region-suffixed name (`cdkd-state-{accountId}-{region}`) is still picked up automatically with a deprecation warning.\n\n## Usage\n\ncdkd has three command families:\n\n- **Top-level commands** (`cdkd deploy` / `destroy` / `diff` / `synth` /\n  `list` / `import` / `orphan` / `publish-assets`) require a CDK app —\n  they synthesize a template to learn what they're operating on.\n- **`cdkd state ...` subcommands** (`state info` / `list` / `resources`\n  / `show` / `orphan` / `destroy` / `migrate` / `refresh-observed`)\n  operate on the S3 state bucket only and do NOT need the CDK app —\n  use them to inspect / clean up state when the source is gone or\n  you don't want to synth. `cdkd state destroy` is the CDK-app-free\n  counterpart of `cdkd destroy`.\n- **`cdkd local ...` subcommands** (`local invoke` / `start-api` /\n  `run-task` / `start-service`) run synthesized workloads locally\n  inside Docker containers — no AWS deploy needed. Modeled on\n  `sam local *` but reads CDK state directly via `--from-state`\n  (cdkd-managed) or `--from-cfn-stack` (CFn-managed). See\n  [Local execution](#local-execution).\n\nOptions like `--app`, `--state-bucket`, and `--context` can be omitted if configured via `cdk.json` or environment variables (`CDKD_APP`, `CDKD_STATE_BUCKET`).\n\n```bash\n# Synth + deploy\ncdkd synth\ncdkd deploy                         # single-stack auto-detected\ncdkd deploy MyStack                 # by name (or 'MyStage/Api' display path)\ncdkd deploy --all\ncdkd deploy --dry-run               # plan only, no changes\ncdkd deploy --no-rollback           # Terraform-style: keep partial state on failure\ncdkd deploy --no-wait               # skip multi-minute waits (CloudFront / RDS / NAT)\n\n# Inspect what would change\ncdkd diff MyStack\ncdkd diff MyStack --fail            # exit 1 on any change (CI gate)\n\n# Drift detection — compare state vs AWS reality (no synth)\ncdkd drift MyStack                  # exit 1 if drift\ncdkd drift MyStack --accept --yes   # state ← AWS\ncdkd drift MyStack --revert --yes   # AWS ← state\n\n# Asset / destroy / unlock\ncdkd publish-assets                 # synth + upload only (typical CI split)\ncdkd destroy MyStack\ncdkd orphan MyStack/MyBucket        # drop one resource from state (AWS resource stays)\ncdkd force-unlock MyStack           # clear stale lock from an interrupted deploy\n\n# Migrate between cdkd and CloudFormation\ncdkd import MyStack --yes           # adopt existing AWS resources into cdkd state\ncdkd export MyStack                 # hand a cdkd-managed stack back to CloudFormation\n\n# State-bucket-only commands (no CDK app needed)\ncdkd state info                     # bucket name, region, schema version\ncdkd state list                     # one row per (stackName, region)\ncdkd state list --tree              # parent → child nested-stack tree\ncdkd state show MyStack             # full state record\ncdkd state resources MyStack        # logical id / type / physical id\ncdkd state destroy MyStack          # delete AWS resources + state, no CDK app\ncdkd state orphan MyStack           # remove state record only (AWS resources stay)\n```\n\nSee **[docs/cli-reference.md](docs/cli-reference.md)** for the full flag\nmatrix (`--concurrency`, `--no-aggressive-vpc-parallel`,\n`--allow-unsupported-properties`, `--role-arn`, etc.), per-command details\nincluding the synth-driven per-resource `cdkd orphan \u003cconstructPath\u003e`\nvariant, and stage / wildcard pattern matching.\n\n## `--no-wait`: skip async-resource waits\n\nCloudFront / RDS / ElastiCache / NAT Gateway typically take 1–15\nminutes to fully provision. By default cdkd waits (matching CFn).\n`cdkd deploy --no-wait` returns as soon as the create call returns\nand lets AWS finish in the background — handy for CI where nothing\nin the deploy flow needs the resource fully active. **Deploy-only**:\n`cdkd destroy` always waits (NAT in `deleting` state holds ENIs and\nwould `DependencyViolation` sibling deletes).\n\nSee [docs/cli-reference.md](docs/cli-reference.md#--no-wait-skip-async-resource-waits)\nfor per-resource caveats (NAT egress, RDS final-snapshot timing,\netc.).\n\n## Local execution\n\nThe `cdkd local` family runs AWS workloads on the developer's machine\nvia Docker — Lambda functions, API Gateway routes, ECS tasks, and\nlong-running ECS services — without an AWS deploy. Modeled on `sam local *` but reuses cdkd's\nsynthesis / asset / construct-path plumbing — no `template.yaml` to\nmaintain, no `cdk synth | sam ...` round-trip.\n\n| Subcommand | Emulates |\n| --- | --- |\n| `cdkd local invoke \u003ctarget\u003e` | One-shot Lambda invoke via the AWS Lambda Runtime Interface Emulator (RIE) |\n| `cdkd local start-api` | Long-running HTTP server for REST v1 / HTTP API / Function URL routes |\n| `cdkd local run-task \u003ctarget\u003e` | ECS RunTask — every container in a task definition started on a per-task docker network |\n| `cdkd local start-service \u003ctarget\u003e` | Long-running ECS Service emulator — `DesiredCount` replicas with restart-on-exit (no local load balancer in v1) |\n| `cdkd local invoke-agentcore \u003ctarget\u003e` | One-shot Bedrock AgentCore Runtime invoke (HTTP `/invocations` / MCP `/mcp` / A2A `/a2a` / AGUI / WebSocket `--ws`) |\n| `cdkd local start-agentcore [target]` | Long-running serve of a Bedrock AgentCore Runtime against a warm container (all four protocols): HTTP / AGUI serve `POST /invocations` + `GET /ping` plus the `/ws` bridge (injects the session-id / Authorization a header-less browser client cannot set); MCP serves `/mcp`, A2A serves `/`. `--sigv4` / `--watch` supported |\n| `cdkd local start-alb \u003ctargets...\u003e` | Long-running local ALB front-door (HTTP + HTTPS listeners, path / host / header / weighted / redirect / fixed-response routing, authenticate-cognito / authenticate-oidc) for ECS / Lambda backing services |\n| `cdkd local start-cloudfront [target]` | Long-running local CloudFront distribution — viewer-request -\u003e S3 / Lambda Function URL origin -\u003e viewer-response pipeline, CloudFront Functions run in-process (Function URL origins use Docker/RIE) |\n\nThe Docker-backed commands above require Docker. Pass `--from-state`\n(cdkd-deployed) or `--from-cfn-stack` (cdk-deployed / CFn-managed) to\nsubstitute deployed physical IDs into intrinsic-valued env vars /\nsecrets / image URIs; without either, intrinsic values are dropped with\na per-key warning (matches `sam local *`). The two flags are mutually\nexclusive. `start-cloudfront` carries both `--from-state` and\n`--from-cfn-stack` too (since cdk-local 0.128.0 / issue #766); a\nCloudFront-Functions + S3-origin distribution still serves entirely\nin-process (no Docker), while a Lambda Function URL origin runs via the\nRIE container.\n\n### `local invoke`\n\n```bash\ncdkd local invoke MyStack/Handler                    # one-shot invoke\ncdkd local invoke MyStack/Handler --event events/get.json\ncdkd local invoke MyStack/Handler --from-state       # OR --from-cfn-stack\n```\n\nAll AWS Lambda runtimes (Node.js / Python / Ruby / Java / .NET /\n`provided.al2023`), ZIP and container Lambdas, same-stack Lambda Layers\nbind-mounted at `/opt`.\n\n### `local start-api`\n\n```bash\ncdkd local start-api                                 # one HTTP server per discovered API\ncdkd local start-api MyStack/MyHttpApi --watch       # filter + hot reload\ncdkd local start-api --from-state                    # OR --from-cfn-stack\n\n# Typical shape — the bare `--from-cfn-stack` flag auto-resolves to the\n# routed stack's name (here `MyStack`). Pass an explicit value only when\n# the deployed CFn stack name differs from the CDK stack name.\ncdkd local start-api MyStack/MyHttpApi --from-cfn-stack\n```\n\nREST v1 + HTTP API v2 + Function URL with all integration kinds\n(AWS_PROXY / MOCK / HTTP_PROXY / HTTP / AWS Lambda non-proxy via\nhand-rolled VTL), authorizers (Lambda / Cognito / HTTP v2 JWT /\nAWS_IAM SigV4 on REST v1 + Function URL), CORS, stage variables,\n`--watch` hot reload.\n\n### `local run-task`\n\n```bash\ncdkd local run-task MyStack/MyService/TaskDef\ncdkd local run-task MyTaskDef --from-state           # OR --from-cfn-stack\n```\n\nEvery container in the task definition on a per-task docker network\nwith the AWS-published ECS metadata sidecar.\n\n### `local start-service`\n\n```bash\ncdkd local start-service MyStack/Orders MyStack/Web  # multiple services in one invocation\ncdkd local start-service MyStack/Orders --from-state # OR --from-cfn-stack\ncdkd local start-service MyStack/Web --watch         # hot reload (sub-second on interpreted handlers)\n```\n\nLong-running ECS Service emulator: `DesiredCount` replicas with\nrestart-on-exit, cross-service Service Connect / Cloud Map DNS\ndiscovery (peer containers reach each other by `\u003cdiscoveryName\u003e.\u003cnamespace\u003e`).\nNo local load-balancer in v1. `--watch` re-synths on every CDK source edit\nand reloads one replica at a time — source-only edits on\ninterpreted-language handlers (Node / Python / Ruby / shell) take a\nbind-mount fast path (`docker cp` + `docker restart`; no rebuild);\nDockerfile / dependency manifest / compiled-language source edits fall\nthrough to a full rebuild + shadow boot + atomic swap.\n\n### `local start-alb`\n\n```bash\ncdkd local start-alb MyStack/MyAlb --lb-port 80=8080 # remap privileged listener port\ncdkd local start-alb MyStack/MyAlb --from-state      # OR --from-cfn-stack\ncdkd local start-alb MyStack/MyAlb --watch           # hot reload (sub-second on interpreted handlers)\n```\n\nLong-running local ALB front-door: names an `AWS::ElasticLoadBalancingV2::LoadBalancer`,\nboots every ECS service behind its listeners, and stands up a local\nHTTP / HTTPS front-door on each listener port that round-robins across\nthe running replicas and routes its listener rules across the backing\nservices. Forward / redirect / fixed-response actions; ECS or Lambda\ntargets; authenticate-cognito / authenticate-oidc via a local Bearer-JWT\ncheck. `--watch` reloads one backing-replica at a time across edits —\ninterpreted-handler source edits go through the bind-mount fast path\n(no rebuild); Dockerfile / dependency / compiled-source edits fall\nthrough to a rebuild + atomic front-door pool swap.\n\n### `local start-cloudfront`\n\n```bash\ncdkd local start-cloudfront                          # interactive picker\ncdkd local start-cloudfront MyStack/MyDistribution   # name the distribution\ncdkd local start-cloudfront MyStack/MyDistribution --watch   # re-synth + swap on edit\ncdkd local start-cloudfront MyStack/MyDistribution --tls      # real HTTPS termination\n```\n\nServes a CloudFront distribution's **viewer-request -\u003e S3 origin -\u003e\nviewer-response** pipeline locally so a routing-function change is\nverifiable in seconds instead of a deploy round-trip. The distribution's\n`AWS::CloudFront::Function`s (URL rewrites, trailing-slash normalization,\nSPA fallback, header tweaks) run in-process in a `node:vm` sandbox; the\nS3 origin content is the `BucketDeployment` source asset resolved out of\nthe cloud assembly, served with `DefaultRootObject` and\n`CustomErrorResponses`. Path patterns route across the default + ordered\ncache behaviors. Pure-local: no Docker, no AWS call — `--watch` is just\nre-synth + an in-memory routing-model swap. S3 origins only (custom /\nLambda@Edge origins are warn-and-skip); `--origin \u003cid\u003e=\u003cdir\u003e` points an\norigin at a local directory when `BucketDeployment` resolution can't.\n\nSee **[docs/local-emulation.md](docs/local-emulation.md)** for the\nfull reference — runtimes, target resolution, every flag, integration\nand authorizer detail, route precedence, container pool, networking,\n`--from-cfn-stack` semantics, v1 scope.\n\n## Rollback behavior\n\nWhen a deploy fails mid-stack (e.g. a resource hits a validation error\nor AWS rejects the request), cdkd by default **rolls back the\nalready-completed resources in the same deploy** so the stack state\nstays consistent — every resource cdkd just created in this run is\ndeleted in reverse dependency order, the state record is updated to\nmatch, and the CLI exits non-zero. Resources that existed before this\ndeploy are NOT touched.\n\nPass `cdkd deploy --no-rollback` to skip the rollback (Terraform-style:\nthe partial state is preserved so you can `cdkd state show \u003cstack\u003e`,\ninspect what landed, fix the underlying issue, and re-run `cdkd deploy`\nto continue from the half-deployed state). Recommended only when you\nplan to manually inspect / repair; the default is safer for CI.\n\nMid-deploy state is also saved per-resource as work completes, so even\nif cdkd itself crashes between the failure and the rollback, the state\nfile accurately reflects what's on AWS and a follow-up `cdkd destroy`\nwon't orphan anything.\n\n## Importing existing resources\n\n`cdkd import` adopts AWS resources that are already deployed (via\n`cdk deploy`, manual creation, or another tool) into cdkd state so the\nnext `cdkd deploy` updates them in-place instead of CREATEing duplicates.\n\n`cdkd import --migrate-from-cloudformation` extends this to migrate a\n**whole CloudFormation stack** off CFn in a single command: cdkd reads\nthe source CFn stack's `(logicalId, physicalId)` mappings, adopts every\nresource into cdkd state, then retires the source CFn stack (injects\n`DeletionPolicy: Retain` + `UpdateReplacePolicy: Retain` on every\nresource → `UpdateStack` → `DeleteStack`) so the AWS resources stay\nintact but are no longer tracked by CFn. After the command finishes,\nthe stack is managed by `cdkd deploy`. This is the reverse direction\nof `cdkd export` (see below).\n\n```bash\n# Adopt a whole stack previously deployed by cdk deploy (tag-based auto-lookup).\ncdkd import MyStack --yes\n\n# Adopt only specific resources (CDK CLI parity).\ncdkd import MyStack --resource MyBucket=my-bucket-name\n\n# Migrate off CloudFormation in one shot — adopt + retire the source CFn stack.\ncdkd import MyStack --migrate-from-cloudformation --yes\n```\n\nSee **[docs/import.md](docs/import.md)** for the full guide: three import\nmodes (auto / selective / hybrid), `--resource-mapping` CDK CLI\ncompatibility, CloudFormation migration flow, provider coverage, and the\nparity matrix vs upstream `cdk import`.\n\n## Exporting a stack back to CloudFormation\n\n`cdkd export` is the mirror of `cdkd import`: it hands a cdkd-managed\nstack back to CloudFormation via a CFn `ChangeSetType=IMPORT` changeset.\nAWS resources are unchanged across the migration; cdkd state for the\nexported stack is deleted on success. From then on the stack is managed\nby `cdk deploy` / `aws cloudformation`. Accepts JSON and YAML templates\n(shorthand intrinsics round-trip).\n\n```bash\ncdkd export MyStack                           # confirmation prompt; CFn stack name = cdkd stack name\ncdkd export MyStack --cfn-stack-name MyStack-CFn\ncdkd export MyStack --dry-run                 # print the import plan, do not call CFn\ncdkd export MyStack --include-non-importable  # 2-phase: IMPORT importable + CFn-CREATE Custom Resources\ncdkd export MyApp                             # nested-stack tree: leaf-first per-stack IMPORT loop\n```\n\n**Lambda-backed Custom Resources** (`Custom::*` /\n`AWS::CloudFormation::CustomResource`) are NOT directly CFn-importable.\n`--include-non-importable` opts into a 2-phase migration that re-CREATEs\nthem through CFn — the Custom Resource Lambda must be idempotent.\n**Nested stacks** are supported via a leaf-first per-stack IMPORT loop\n(AWS rejects `--include-nested-stacks` for IMPORT changesets).\n\nSee **[docs/import.md](docs/import.md)** for the full guide — Custom Resource\n2-phase flow, nested-stack adoption mechanics (`--cfn-child-stack-name`\nper-child overrides, AWS's \"Nest an existing stack\" pattern), and the\ndesign rationale at [docs/design/464-nested-stacks-export-import.md](docs/design/464-nested-stacks-export-import.md).\n\n## Drift detection\n\n`cdkd drift` (state-driven; no synth) compares each managed resource\nagainst AWS reality and reports divergence — including console-side\nchanges to keys you did NOT template (S3 public-access-block, IAM Role\ntags, Lambda env keys, etc.).\n\n```bash\ncdkd drift                       # auto-detect single stack, exit 1 if drift\ncdkd drift MyStack --json        # machine-readable, for CI gating\ncdkd drift MyStack --accept --yes   # state ← AWS (catch up after a console edit)\ncdkd drift MyStack --revert --yes   # AWS ← state (undo a console edit)\ncdkd state refresh-observed MyStack # populate the drift baseline without redeploying\n```\n\nSee **[docs/cli-reference.md `cdkd drift`](docs/cli-reference.md#cdkd-drift)**\nfor the full reference: `--no-capture-observed-state` deploy opt-out\n(per-command vs per-project, mid-flight reversibility), v2→v3 state\nupgrade flow, exit codes, and what changes when capture is off.\n\n## Orphan vs destroy\n\n`destroy` deletes the AWS resources **and** the state record;\n`orphan` deletes **only** the state record (AWS resources stay\nintact, just no longer tracked by cdkd). Mirrors aws-cdk-cli's\n`cdk orphan`.\n\nTwo `orphan` variants at different granularities:\n\n- `cdkd orphan \u003cconstructPath\u003e...` — synth-driven, **per-resource**.\n  Rewrites every sibling reference (Ref / Fn::GetAtt / Fn::Sub /\n  dependencies) so the next deploy doesn't re-create the orphan.\n- `cdkd state orphan \u003cstack\u003e...` — state-driven, **whole-stack**.\n  Removes the entire state record. Works without the CDK app.\n\nBoth `cdkd destroy` (synth-driven) and `cdkd state destroy`\n(state-driven, no synth) delete AWS resources + state.\n\n## VPC route DependsOn relaxation (on by default)\n\nCDK injects defensive `DependsOn` from VPC Lambdas onto private-subnet\nroutes. The dependency is real at runtime but NOT required at deploy\ntime. cdkd drops it by default so CloudFront + Lambda::Url propagation\nruns in parallel with NAT stabilization (~50% faster on VPC+Lambda+CloudFront\nstacks; bench-cdk-sample 398s → 181s). Pass\n`cdkd deploy --no-aggressive-vpc-parallel` to opt out (e.g. when a\nCustom Resource synchronously invokes a VPC Lambda outside cdkd's\nLambda-ServiceToken Active wait).\n\nSee [docs/cli-reference.md](docs/cli-reference.md) for the full\ntype-pair allowlist and trade-off notes.\n\n## `--remove-protection`: one-shot bypass for protected resources\n\n`cdkd destroy --remove-protection` (and `cdkd state destroy --remove-protection`)\nflips every protection flag off in-place before each provider's delete\nAPI call, so a destroy proceeds without an intermediate edit / redeploy.\nCovers stack-level `terminationProtection` (logged as a WARN) AND\nresource-level protection on these types:\n\n| Resource type | Protection field |\n| --- | --- |\n| `AWS::Logs::LogGroup` | `DeletionProtectionEnabled` |\n| `AWS::RDS::DBInstance` | `DeletionProtection` |\n| `AWS::RDS::DBCluster` | `DeletionProtection` |\n| `AWS::DocDB::DBCluster` | `DeletionProtection` (DocDB DBInstance has no `DeletionProtection` field, so per-instance bypass is a no-op) |\n| `AWS::Neptune::DBCluster` | `DeletionProtection` |\n| `AWS::Neptune::DBInstance` | `DeletionProtection` |\n| `AWS::DynamoDB::Table` | `DeletionProtectionEnabled` |\n| `AWS::DynamoDB::GlobalTable` | `DeletionProtectionEnabled` (CDK v2 `dynamodb.TableV2`) |\n| `AWS::EC2::Instance` | `DisableApiTermination` |\n| `AWS::ElasticLoadBalancingV2::LoadBalancer` | attribute `deletion_protection.enabled` |\n| `AWS::Cognito::UserPool` | `DeletionProtection` (`ACTIVE` / `INACTIVE`) |\n| `AWS::AutoScaling::AutoScalingGroup` | `DeletionProtection` (`none` / `prevent-force-deletion` / `prevent-all-deletion`) — flag also sets `ForceDelete: true` so AWS terminates running instances as part of the delete |\n\nA single `--remove-protection` covers every type listed above (no\nper-type variant). The interactive confirm prompt switches to\n`y/N` (requiring an explicit `y` for the destructive bypass);\n`--yes` / `-y` / `-f` skips it.\n\nOut of scope: types where AWS doesn't expose a synchronous \"flip\nprotection off\" API call (CloudFront Distributions, Lambda function\nreserved concurrency, S3 bucket retention, etc.).\n\n## `publish-assets`: synth + build + publish, no deploy\n\n`cdkd publish-assets` runs the asset half of the deploy pipeline\nonly — synthesize, build Docker images, upload file assets to S3,\npush images to ECR — and stops. No state writes, no provisioning.\nTypical CI split where one runner builds + uploads assets and a\nseparate runner deploys.\n\n```bash\ncdkd publish-assets                  # all stacks (or auto-detect single stack)\ncdkd publish-assets MyStack          # specific stack\ncdkd publish-assets -a cdk.out       # skip synth, use pre-synthesized assembly\n```\n\nSee [docs/cli-reference.md](docs/cli-reference.md#publish-assets-synth--build--publish-no-deploy)\nfor stack-selection rules and concurrency knobs.\n\n## Compatibility\n\ncdkd supports the standard CloudFormation surface — intrinsic functions,\npseudo parameters, parameters / conditions, cross-stack / cross-region\nreferences, asset publishing, custom resources, and so on. See\n**[docs/supported-features.md](docs/supported-features.md)** for the\nfull reference. For per-resource-type provisioning support (SDK Providers\nvs Cloud Control API fallback), see\n**[docs/supported-resources.md](docs/supported-resources.md)**.\n\n**Property-level coverage is incremental.** SDK Providers wire most but not every CFn property of a supported type. cdkd fails fast at pre-flight when a template uses a not-yet-implemented property, with the property name + a 1-click issue link. `--allow-unsupported-properties \u003cType\u003e:\u003cProp\u003e,...` is the safety valve when this is too strict (e.g. mid-life update on an existing resource); avoid it on security-meaningful properties (encryption / IAM / TLS). See [docs/cli-reference.md](docs/cli-reference.md#--allow-unsupported-properties-deploy).\n\n## State Management\n\nState is stored in S3 with optimistic locking via S3 Conditional Writes\n(no DynamoDB required). Keys are scoped by `(stackName, region)` so the\nsame stack deployed to two regions has two independent state files.\n\n| Setting | CLI | cdk.json | Env var | Default |\n|---------|-----|----------|---------|---------|\n| Bucket | `--state-bucket` | `context.cdkd.stateBucket` | `CDKD_STATE_BUCKET` | `cdkd-state-{accountId}` (legacy `cdkd-state-{accountId}-{region}` is still read with a deprecation warning — run `cdkd state migrate` to consolidate) |\n| Prefix | `--state-prefix` | - | - | `cdkd` |\n\nThe state bucket is shared across all CDK apps in the same account by\ndefault. To isolate apps, pass different `--state-prefix` values.\n`cdkd destroy --all` only targets stacks from the current CDK app\n(determined by synthesis), not all stacks in the bucket.\n\nSee **[docs/state-management.md](docs/state-management.md)** for the full\nspec: S3 key layout, optimistic-locking mechanism (ETag-based), state\nschema, legacy `version: 1` migration, bucket-name migration via\n`cdkd state migrate`, and troubleshooting.\n\n## Deployment events (`cdkd events`)\n\nEvery `cdkd deploy` / `cdkd destroy` run records a structured event\nstream to S3 — cdkd's local equivalent of CloudFormation's\n`DescribeStackEvents`. Read it back with `cdkd events \u003cstack\u003e`:\n\n```bash\ncdkd events MyStack                 # list runs, newest first\ncdkd events MyStack --run \u003crunId\u003e   # one run's full event stream\ncdkd events MyStack --format json   # machine-readable (AI-agent hand-off)\n```\n\nEvents are persisted as JSONL under a `deployments/` key family separate\nfrom `state.json` (no state schema bump), so a destroyed stack's failure\nhistory stays readable. Recording is best-effort and never blocks the\nrun; events carry error + metadata only (never resource properties). See\n**[docs/deployment-events.md](docs/deployment-events.md)** for the full\nreference.\n\n## Stack Outputs\n\nCDK's `CfnOutput` constructs are resolved and stored in the state file:\n\n```typescript\n// In your CDK code\nnew cdk.CfnOutput(this, 'BucketArn', {\n  value: bucket.bucketArn,  // Uses Fn::GetAtt internally\n  description: 'ARN of the bucket',\n});\n```\n\nAfter deployment, outputs are resolved and printed at the end of `cdkd deploy` (matching CDK CLI's format) and saved to the S3 state file:\n\n```text\nDeployment Summary:\n  Stack: MyStack\n  ...\n  Duration: 21.25s\n\nOutputs:\n  MyStack.BucketArn = arn:aws:s3:::actual-bucket-name-xyz\n\n✓ Deployment completed successfully\n```\n\n```json\n{\n  \"outputs\": {\n    \"BucketArn\": \"arn:aws:s3:::actual-bucket-name-xyz\"\n  }\n}\n```\n\n**Key differences from CloudFormation**:\n\n- CloudFormation: Outputs accessible via `aws cloudformation describe-stacks`\n- cdkd: Outputs saved in S3 state file (e.g., `s3://bucket/cdkd/MyStack/us-east-1/state.json`)\n- Both print outputs to stdout after a successful deploy\n- Both resolve intrinsic functions (Ref, Fn::GetAtt, etc.) to actual values\n\n## Exit codes\n\ncdkd commands distinguish three outcomes via the process exit code so\nCI / bench scripts can react without grepping log output:\n\n| Exit | Meaning |\n|------|---------|\n| `0` | Success — command completed and no resources are in an error state |\n| `1` | Command-level failure — auth error, bad arguments, synth crash, unhandled exception |\n| `2` | **Partial failure** — work completed but one or more resources failed (state.json is preserved, re-running typically resolves it) |\n\nExit `2` is currently emitted by `cdkd destroy` and `cdkd state\ndestroy` when one or more per-resource deletes fail. The summary line\nalso switches from `✓ Stack X destroyed` to `⚠ Stack X partially\ndestroyed (...). State preserved — re-run 'cdkd destroy' / 'cdkd\nstate destroy' to clean up.` so the visual marker matches the exit\ncode.\n\n## License\n\nApache 2.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgo-to-k%2Fcdkd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgo-to-k%2Fcdkd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgo-to-k%2Fcdkd/lists"}