

This is the AWS CDK v2 Developer Guide. The older CDK v1 entered maintenance on June 1, 2022 and ended support on June 1, 2023.

# Perform programmatic actions using the CDK Toolkit Library
<a name="toolkit-library"></a>

## Understanding the CDK Toolkit Library
<a name="toolkit-library-intro"></a>

The CDK Toolkit Library enables you to perform CDK actions programmatically through code instead of using CLI commands. You can use this library to create custom tools, build specialized CLI applications, and integrate CDK capabilities into your development workflows.

 **Manage your infrastructure lifecycle with programmatic control**   
The CDK Toolkit Library provides programmatic interfaces for the following CDK actions:  
+  **Synthesis** - Generate AWS CloudFormation templates and deployment artifacts.
+  **Deployment** - Provision or update infrastructure using CloudFormation templates.
+  **Refactor** - Preserve deployed resources when refactoring CDK code, such as renaming constructs or moving them between stacks.
+  **List** - View information about stacks and their dependencies.
+  **Watch** - Monitor CDK apps for local changes.
+  **Rollback** - Return stacks to their last stable state.
+  **Destroy** - Remove CDK stacks and associated resources.

 **Enhance and customize your infrastructure management**   
+  **Control through code** - Integrate infrastructure management directly into your applications and build responsive deployment pipelines.
+  **Manage cloud assemblies** - Create, inspect, and transform your infrastructure definitions before deployment.
+  **Customize deployments** - Configure parameters, rollback behavior, and monitoring to match your requirements.
+  **Preserve resources during refactoring** - Automatically detect and preserve resources when you refactor CDK code.
+  **Handle errors precisely** - Implement structured error handling with detailed diagnostic information.
+  **Tailor communications** - Configure custom progress indicators and logging through `IoHost` implementations.
+  **Connect with AWS ** - Configure profiles, Regions, and authentication flows programmatically.

## Choosing when to use the CDK Toolkit Library
<a name="toolkit-library-intro-when"></a>

The CDK Toolkit Library is particularly valuable when you need to:
+ Automate infrastructure deployments as part of CI/CD pipelines.
+ Build custom deployment tools tailored to your organization’s needs.
+ Integrate CDK actions into existing applications or platforms.
+ Create specialized deployment workflows with custom validation or approval steps.
+ Implement advanced infrastructure management patterns across multiple environments.
+ Automate refactoring operations to preserve resources when you refactor CDK code.

## Using the CDK Toolkit Library
<a name="toolkit-library-intro-example"></a>

The following example shows how to create and deploy a simple S3 bucket using the CDK Toolkit Library:

```
// Import required packages
import { Toolkit } from '@aws-cdk/toolkit-lib';
import { App, Stack } from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';

// Create and configure the CDK Toolkit
const toolkit = new Toolkit();

// Create a cloud assembly source with an inline app
const cloudAssemblySource = await toolkit.fromAssemblyBuilder(async () => {
   const app = new App();
   const stack = new Stack(app, 'SimpleStorageStack');

   // Create an S3 bucket in the stack
   new s3.Bucket(stack, 'MyFirstBucket', {
      versioned: true
   });

   return app.synth();
});

// Deploy the stack
await toolkit.deploy(cloudAssemblySource);
```

 **What you can do next**   
+  **Automate deployments** - Trigger deployments programmatically and add pre/post deployment steps.
+  **Integrate with systems** - Connect with CI/CD workflows, custom tools, and monitoring solutions.
+  **Control deployment details** - Configure fine-grained options for stack selection and multi-environment deployments.
+  **Enhance reliability** - Implement production-ready error handling and deployment progress tracking.
+  **Automate refactoring** - Detect and preserve resources when you refactor CDK code.

## Next steps
<a name="toolkit-library-intro-next"></a>

To begin using the CDK Toolkit Library, see [Get started with the CDK Toolkit Library](toolkit-library-gs.md).

## Learn more
<a name="toolkit-library-intro-learn"></a>

To learn more about the CDK Toolkit Library, see the following:
+  [ReadMe](https://www.npmjs.com/package/@aws-cdk/toolkit-lib) in the *@aws-cdk/toolkit-lib* `npm` package.
+  [AWS CDK Toolkit Library API Reference](https://docs.aws.amazon.com/cdk/api/toolkit-lib/).

# Getting started with the CDK Toolkit Library
<a name="toolkit-library-gs"></a>

Get started with using the AWS CDK Toolkit Library to programmatically perform CDK actions, such as synthesis and deployment, in your code.

## Prerequisites
<a name="toolkit-library-gs-prerequisites"></a>

1. Supported version of Node.js installed.

1.  AWS credentials configured.

1. Basic familiarity with the AWS CDK.

For more information, see [AWS CDK prerequisites](prerequisites.md).

## Step 1: Installing the CDK Toolkit Library
<a name="toolkit-library-gs-install"></a>

Install the CDK Toolkit Library package in your project’s development environment by running the following:

```
npm install --save @aws-cdk/toolkit-lib
```

## Step 2: Initializing the CDK Toolkit Library
<a name="toolkit-library-gs-initialize"></a>

Create a CDK Toolkit instance to perform programmatic actions on your CDK app.

```
import { Toolkit } from '@aws-cdk/toolkit-lib';

const toolkit = new Toolkit({
    // Optional configuration options go here
});
```

You can customize the CDK Toolkit instance during creation. For instructions, see [Configure your CDK Toolkit instance](toolkit-library-configure.md).

## Step 3: Creating a cloud assembly source for your CDK app
<a name="toolkit-library-gs-ca"></a>

A cloud assembly source provides instructions for generating CloudFormation templates from your CDK app. You can create one in multiple ways. The following are a few examples:

1.  **An inline assembly builder function**:

   ```
   import * as cdk from 'aws-cdk-lib';
   
   const cloudAssemblySource = await toolkit.fromAssemblyBuilder(async () => {
     const app = new cdk.App();
     new MyStack(app, 'MyStack');
     return app.synth();
   });
   ```

1.  **An existing CDK app file**:

   ```
   const cloudAssemblySource = await toolkit.fromCdkApp("ts-node app.ts");
   ```

For more information, see [Configure cloud assembly sources](toolkit-library-configure-ca.md).

## Step 4: Defining programmatic actions for your CDK app
<a name="toolkit-library-gs-define"></a>

Now that you’ve created a CDK Toolkit instance and cloud assembly source, you can start to define programmatic actions. The following is a basic example that creates a deployment of the `MyStack` stack:

```
import { StackSelectionStrategy } from '@aws-cdk/toolkit-lib';

await toolkit.deploy(cloudAssemblySource, {
  stacks: {
    strategy: StackSelectionStrategy.PATTERN_MUST_MATCH, // Deploy only stacks that exactly match the provided patterns
    patterns: ["MyStack"],
  },
});
```

## Step 5: Customizing the CDK Toolkit further
<a name="toolkit-library-gs-customize"></a>

You can configure and customize the CDK Toolkit further for your needs:
+  **Messages and interactions** - Configure how the CDK Toolkit communicates with users and applications. See [Configure messages & interactions](toolkit-library-configure-messages.md).
+  **Error handling** - Implement structured error handling for CDK operations. See [Configure error handling](toolkit-library-configure.md#toolkit-library-configure-errors).

## Additional resources
<a name="toolkit-library-gs-resources"></a>

For more information on the CDK Toolkit Library `npm` package, see the [ReadMe](https://www.npmjs.com/package/@aws-cdk/toolkit-lib) in the *@aws-cdk/toolkit-lib* `npm` package.

For API reference information, see the [CDK Toolkit Library API reference](https://docs.aws.amazon.com/cdk/api/toolkit-lib/).

# Configuring CDK Toolkit programmatic actions
<a name="toolkit-library-actions"></a>

The AWS CDK Toolkit Library provides programmatic interfaces for application lifecycle actions such as synthesis, deployment, and stack management. This guide explains how to use each action in your code.

## Generating cloud assemblies with synth
<a name="toolkit-library-actions-synth"></a>

The `synth` action generates a cloud assembly from your cloud assembly source. For more information about synthesis, see [Configure and perform CDK stack synthesis](configure-synth.md). A cloud assembly contains the following deployment artifacts from your CDK app:
+  AWS CloudFormation templates that define your infrastructure.
+ Assets such as Lambda function code or Docker images.
+ Deployment metadata and configuration.

Here’s how to use the `synth` action to create a cloud assembly:

```
// Create a toolkit instance
const toolkit = new Toolkit();

// Create a cloud assembly source from a TypeScript app
const cloudAssemblySource = await toolkit.fromCdkApp("ts-node app.ts");

// Generate a cloud assembly
const cloudAssembly = await toolkit.synth(cloudAssemblySource);

// Use the cloud assembly for operations
await toolkit.list(cloudAssembly);
await toolkit.deploy(cloudAssembly);
await toolkit.diff(cloudAssembly);

// Query information from the cloud assembly
const template = cloudAssembly.getStack("my-stack").template;
```

**Tip**  
Using a cloud assembly can optimize performance when you need to perform multiple operations, since synthesis only happens once. For more information about managing cloud assemblies, including caching and disposal, see [Create and manage cloud assemblies](toolkit-library-configure-ca.md#toolkit-library-configure-ca-cache).

## Viewing stack information with list
<a name="toolkit-library-actions-list"></a>

The `list` action retrieves information about the stacks in your CDK application, including their dependencies and current status. Use this action to inspect your infrastructure before deployment or to generate reports.

```
import { StackSelectionStrategy } from '@aws-cdk/toolkit-lib';

// Get information about specific stacks
const stackDetails = await toolkit.list(cloudAssemblySource, {
  stacks: {
    strategy: StackSelectionStrategy.PATTERN_MUST_MATCH,
    patterns: ["my-stack"], // Only include stacks matching this pattern
  }
});

// Process the returned stack information
for (const stack of stackDetails) {
  console.log(`Stack: ${stack.id}, Dependencies: ${stack.dependencies}`);
}
```

## Provisioning infrastructure with deploy
<a name="toolkit-library-actions-deploy"></a>

The `deploy` action provisions or updates your infrastructure in AWS using the cloud assembly produced during synthesis. For an introduction to deploying, see [Deploy AWS CDK applications](deploy.md). You can control deployment options such as stack selection, parameter values, and rollback behavior.

```
// Deploy stacks with parameter values
await toolkit.deploy(cloudAssemblySource, {
  parameters: StackParameters.exactly({
    "MyStack": {
      "BucketName": "amzn-s3-demo-bucket"
    }
  })
});
```

The deploy action supports different deployment methods to accommodate various workflows. For most scenarios, especially in production environments, we recommend using the default deployment method which uses CloudFormation change sets. For development environments where iteration speed is important, you can use alternative methods like hotswap.

```
import { StackSelectionStrategy } from '@aws-cdk/toolkit-lib';

// Deploy using default deployment method (recommended for production)
await toolkit.deploy(cloudAssemblySource, {
  parameters: StackParameters.exactly({
    "MyStack": {
      "BucketName": "amzn-s3-demo-bucket"
    }
  })
});

// For development environments only: Deploy with hotswap for faster iterations
// Note: We recommend using default deployment methods for production environments
await toolkit.deploy(cloudAssemblySource, {
  deploymentMethod: { method: "hotswap", fallback: true }, // Faster but introduces drift
  stacks: {
    strategy: StackSelectionStrategy.PATTERN_MUST_MATCH,
    patterns: ["dev-stack"]
  }
});
```

## Preserving deployed resources with refactor
<a name="toolkit-library-actions-refactor"></a>

**Important**  
The refactor action is in preview release and is subject to change.

The `refactor` action preserves deployed resources when you refactor CDK code such as renaming constructs or moving them between stacks. Without this feature, these changes would cause CloudFormation to replace resources, potentially leading to service interruptions or data loss.

The refactor action automatically computes mappings by comparing your current code with the deployed state. It verifies that your CDK application contains exactly the same set of resources as the deployed state, differing only in their locations in the construct tree. If it detects any resource additions, deletions, or modifications, the refactoring operation will be rejected with an error message.

Once it computes the mappings, the refactor action uses CloudFormation’s refactoring API to update the logical IDs of resources without replacing them. If it encounters ambiguous mappings (where multiple possible mappings exist), you can provide explicit overrides to resolve these ambiguities.

```
// Perform refactoring operation to preserve resources
await toolkit.refactor(cloudAssemblySource);

// With optional overrides to resolve ambiguities
await toolkit.refactor(cloudAssemblySource, {
  overrides: {
    "environments": [
      {
        "account": "123456789012",
        "region": "us-east-2",
        "resources": {
          "StackA.OldName": "StackA.NewName"
        }
      }
    ]
  }
});
```

**Important**  
Refactoring operations must be performed separately from other actions, such as adding new resources, deleting resources, or modifying resource properties. If you need to make such changes, you should first deploy those changes separately, and then use refactoring to reorganize your resources.

**Tip**  
For more information about CDK refactoring, including how it works and when to use it, see [Preserve deployed resources when refactoring CDK code](refactor.md).

## Reverting failed deployments with rollback
<a name="toolkit-library-actions-rollback"></a>

The `rollback` action returns a stack to its last stable state when a deployment fails and cannot be automatically reversed. Use this action to recover from failed deployments that require manual intervention.

```
import { StackSelectionStrategy } from '@aws-cdk/toolkit-lib';

// Roll back stacks to their last stable state
await toolkit.rollback(cloudAssemblySource, {
  orphanFailedResources: false, // When true, removes failed resources from CloudFormation management
  stacks: {
    strategy: StackSelectionStrategy.PATTERN_MUST_MATCH,
    patterns: ["failed-stack"]
  }
});
```

## Monitoring changes with watch
<a name="toolkit-library-actions-watch"></a>

The `watch` action continuously monitors your CDK app for local file changes and automatically performs deployments or hotswaps. This creates a file watcher that runs until your code exits or is terminated.

**Warning**  
Hotswap deployments update resources directly without going through CloudFormation when possible, making updates faster during development. This is enabled by default for the `watch` command. While this speeds up the development cycle, it introduces drift between your CloudFormation templates and deployed resources. Therefore, we recommend that you don’t use hotswaps in production environments.

```
import { StackSelectionStrategy } from '@aws-cdk/toolkit-lib';

// Start watching for changes
const watcher = await toolkit.watch(cloudAssemblySource, {
  include: ["lib/**/*.ts"], // Only watch TypeScript files in the lib directory
  exclude: ["**/*.test.ts"], // Ignore test files
  deploymentMethod: { method: "hotswap" }, // This is the default, shown here for clarity
  stacks: {
    strategy: StackSelectionStrategy.ALL // Watch all stacks
  }
});

// Later in your code, you can explicitly stop watching:
// await watcher.dispose();
```

The watch function returns an `IWatcher` object that allows you to explicitly control when to stop watching. Call the `dispose()` method on this object when you want to end the watch process.

## Removing infrastructure with destroy
<a name="toolkit-library-actions-destroy"></a>

The `destroy` action removes CDK stacks and their associated resources from AWS. Use this action to clean up resources when they’re no longer needed.

**Important**  
The destroy action permanently removes resources without prompting for confirmation, unlike the CLI version of this command. Make sure you have backups of any important data before destroying stacks.

```
import { StackSelectionStrategy } from '@aws-cdk/toolkit-lib';

// Remove specific stacks and their resources
await toolkit.destroy(cloudAssemblySource, {
  stacks: {
    strategy: StackSelectionStrategy.PATTERN_MUST_MATCH,
    patterns: ["dev-stack"], // Only destroy stacks matching this pattern
  }
});
```

# Configuring your CDK Toolkit instance
<a name="toolkit-library-configure"></a>

Learn how to customize your AWS CDK Toolkit Library instance with options for message handling, AWS profile selection, and stack selection strategies. This guide explains the available configuration options and how to implement them effectively to meet your specific deployment requirements.

## Configuring your AWS profile
<a name="toolkit-library-configure-profile"></a>

When you use the CDK Toolkit Library, it makes API calls to AWS using the SDK. While authentication is loaded automatically from your environment, you can explicitly specify which profile to use:

```
import { Toolkit } from '@aws-cdk/toolkit-lib';

// Create a toolkit instance with a specific AWS profile
const toolkit = new Toolkit({
  sdkConfig: { profile: "my-profile" },
});
```

## Configuring stack selection
<a name="toolkit-library-configure-stacks"></a>

Most CDK Toolkit actions require you to specify which stacks to operate on. The ` [StackSelector](https://docs.aws.amazon.com/cdk/api/toolkit-lib/Package/toolkit-lib/Interface/StackSelector/) ` configuration controls this selection.

### Select all stacks
<a name="toolkit-library-configure-stacks-all"></a>

Use this when you want to operate on every stack in your CDK app:

```
import { StackSelectionStrategy } from '@aws-cdk/toolkit-lib';

// Select all stacks in the cloud assembly
await toolkit.deploy(cloudAssemblySource, {
  stacks: {
    strategy: StackSelectionStrategy.ALL_STACKS
  }
});
```

### Select only main assembly stacks
<a name="toolkit-library-configure-stacks-main"></a>

Use this to select only the top-level stacks from the main assembly:

```
// Select only top-level stacks
await toolkit.deploy(cloudAssemblySource, {
  stacks: {
    strategy: StackSelectionStrategy.MAIN_ASSEMBLY
  }
});
```

### Select a single stack
<a name="toolkit-library-configure-stacks-single"></a>

Use this when your assembly contains exactly one stack and you want to assert this condition. If the assembly includes a single stack, it returns that stack. Otherwise, it throws an exception:

```
// Ensure there's exactly one stack and select it
await toolkit.deploy(cloudAssemblySource, {
  stacks: {
    strategy: StackSelectionStrategy.ONLY_SINGLE
  }
});
```

### Select stacks by pattern
<a name="toolkit-library-configure-stacks-pattern"></a>

Use this to select specific stacks by name pattern:

```
// Select stacks matching specific patterns
await toolkit.deploy(cloudAssemblySource, {
  stacks: {
    strategy: StackSelectionStrategy.PATTERN_MUST_MATCH,
    patterns: ["Dev-*", "Test-Backend"],  // Supports wildcards
  }
});
```

**Tip**  
Use `PATTERN_MUST_MATCH_SINGLE` to ensure exactly one stack matches your patterns, or `PATTERN_MATCH` if it’s acceptable for no stacks to match. Pattern matching supports wildcards like "\$1" to match multiple stacks with similar names.

## Configuring error handling
<a name="toolkit-library-configure-errors"></a>

The CDK Toolkit uses structured errors to help you identify and handle issues. Each error includes:
+ A **source** indicating where the error originated (toolkit or user).
+ A specific **error type** (authentication, validation, etc.).
+ A descriptive **message**.

### Handling errors
<a name="toolkit-library-configure-errors-how"></a>

Use the helper methods provided by the CDK Toolkit to detect and handle specific error types:

```
import { ToolkitError } from '@aws-cdk/toolkit-lib';

try {
  // Attempt a CDK Toolkit operation
  await toolkit.deploy(cloudAssemblySource, {
    stacks: { strategy: StackSelectionStrategy.ALL_STACKS }
  });

} catch (error) {
  // Handle specific error types
  if (ToolkitError.isAuthenticationError(error)) {
    // Example: AWS credentials are missing or invalid
    console.error('Authentication failed. Check your AWS credentials.');

  } else if (ToolkitError.isAssemblyError(error)) {
    // Example: Your CDK app has errors in stack definitions
    console.error('CDK app error:', error.message);

  } else if (ToolkitError.isDeploymentError(error)) {
    // Example: CloudFormation deployment failed
    console.error('Deployment failed:', error.message);

  } else if (ToolkitError.isToolkitError(error)) {
    // Handle all other Toolkit errors
    console.error('CDK Toolkit error:', error.message);

  } else {
    // Handle unexpected errors
    console.error('Unexpected error:', error);
  }
}
```

**Important**  
Don’t rely on `instanceof` checks for error types, as they can behave unexpectedly when working with multiple copies of the same package. Always use the provided helper methods like `ToolkitError.isAuthenticationError()`.

## Configuring Toolkit actions
<a name="toolkit-library-configure-actions"></a>

Each CDK Toolkit action (deploy, synth, list, etc.) has its own specific configuration options. These actions allow you to manage the complete lifecycle of your CDK infrastructure. For detailed information on configuring individual actions, see [Configure CDK Toolkit programmatic actions](toolkit-library-actions.md).

**Tip**  
When building automation workflows, consider combining multiple actions in sequence. For example, you might want to `synth` your app, `list` the stacks to verify what will be deployed, and then `deploy` the infrastructure.

# Managing AWS CDK Toolkit Library cloud assembly sources
<a name="toolkit-library-configure-ca"></a>

Use the AWS CDK Toolkit Library to configure cloud assembly sources and customize how you deploy your CDK applications. This guide shows you how to configure cloud assembly sources to meet your deployment requirements and workflow needs.

Before you use the CDK Toolkit, specify a cloud assembly source. A *cloud assembly source* provides instructions for generating a cloud assembly from your CDK app. The resulting cloud assembly contains the synthesized infrastructure artifacts that the CDK Toolkit deploys to AWS.

The CDK Toolkit Library offers several approaches to configure cloud assembly sources, each suited for different scenarios and workflows.

## Selecting a cloud assembly source
<a name="toolkit-library-configure-ca-options"></a>


| Method | Best For | Consideration | 
| --- | --- | --- | 
|   `fromCdkApp`   |  Working with existing CDK applications in any supported language.  |  Requires the appropriate language runtime to be installed.  | 
|   `fromAssemblyBuilder`   |  Creating CDK constructs inline with full control over the synthesis process.  |  Provides low-level access to CDK functionality and can be used to build custom versions of other methods like `fromCdkApp`.  | 
|   `fromAssemblyDirectory`   |  Using pre-synthesized cloud assemblies.  |  Faster execution as synthesis step is skipped.  | 
|  Custom Source  |  Extremely specialized scenarios requiring complete custom implementation.  |  Requires implementing the `ICloudAssemblySource` interface from scratch; lacks built-in functionality like context lookups; rarely needed for most use cases.  | 

## Configuring your cloud assembly source
<a name="toolkit-library-configure-ca-how"></a>

### From an existing CDK app
<a name="toolkit-library-configure-ca-how-app"></a>

Use the `fromCdkApp` method to work with CDK apps written in any supported language. This approach is ideal when you have an existing CDK application and want to deploy it programmatically.

```
import { App } from 'aws-cdk-lib';
import { Toolkit } from '@aws-cdk/toolkit-lib';

// Create a toolkit instance
const toolkit = new Toolkit();

// TypeScript app
const cloudAssemblySource = await toolkit.fromCdkApp("ts-node app.ts");

// Deploy a specific stack from the assembly
await toolkit.deploy(cloudAssemblySource, {
    stacks: ['MyStack']
});

// Other language examples:
// JavaScript app
// const cloudAssemblySource = await toolkit.fromCdkApp("node app.js");

// Python app
// const cloudAssemblySource = await toolkit.fromCdkApp("python app.py");

// Java app
// const cloudAssemblySource = await toolkit.fromCdkApp("mvn -e -q exec:java -Dexec.mainClass=com.mycompany.app.App");
```

### From an inline assembly builder
<a name="toolkit-library-configure-ca-how-builder"></a>

Create a CDK app directly in your code using an assembly builder function. This approach is useful for simple deployments or testing scenarios where you want to define your infrastructure inline.

```
import { App, Stack, RemovalPolicy, StackProps } from 'aws-cdk-lib';
import { Bucket } from 'aws-cdk-lib/aws-s3';
import { Toolkit } from '@aws-cdk/toolkit-lib';
import { Construct } from 'constructs';

// Create a cloud assembly source from an inline CDK app
const cloudAssemblySource = await toolkit.fromAssemblyBuilder(async () => {
    const app = new App();

    // Define a simple stack with an S3 bucket
    class MyStack extends Stack {
        constructor(scope: Construct, id: string, props?: StackProps) {
            super(scope, id, props);

            // Create an S3 bucket
            new Bucket(this, 'MyBucket', {
                versioned: true,
                removalPolicy: RemovalPolicy.DESTROY,
                autoDeleteObjects: true
            });
        }
    }

    // Instantiate the stack
    new MyStack(app, 'MyInlineStack');

    return app.synth();
});

// Deploy using the cloud assembly source
await toolkit.deploy(cloudAssemblySource, {
    stacks: ['MyInlineStack']
});
```

### From an existing assembly directory
<a name="toolkit-library-configure-ca-how-directory"></a>

If you already have a synthesized cloud assembly, you can use it directly. This is useful when you’ve already run `cdk synth` or when working with cloud assemblies generated by CI/CD pipelines.

```
import { Toolkit } from '@aws-cdk/toolkit-lib';

// Create a toolkit instance
const toolkit = new Toolkit();

// Use an existing cloud assembly directory
const cloudAssemblySource = await toolkit.fromAssemblyDirectory("cdk.out");

// Deploy using the cloud assembly source
await toolkit.deploy(cloudAssemblySource, {
    stacks: ['MyStack']
});
```

## Working with cached cloud assemblies
<a name="toolkit-library-configure-ca-cache"></a>

When working with cloud assemblies, you have two options:

1. Use a cloud assembly source directly (simple but may be slower):

   ```
   // Each operation triggers a new synthesis
   await toolkit.deploy(cloudAssemblySource, { /* options */ });
   await toolkit.list(cloudAssemblySource, { /* options */ });
   ```

1. Cache the cloud assembly (faster for multiple operations):

   ```
   // Synthesize once and reuse
   const cloudAssembly = await toolkit.synth(cloudAssemblySource);
   try {
     // Multiple operations use the same assembly
     await toolkit.deploy(cloudAssembly, { /* options */ });
     await toolkit.list(cloudAssembly, { /* options */ });
   } finally {
     // Clean up when done
     await cloudAssembly.dispose();
   }
   ```

Use cached assemblies when:
+ You’re performing multiple operations (deploy, list, diff, etc.).
+ Your CDK app doesn’t change frequently during operations.
+ You want faster performance.

Use cloud assembly sources directly when:
+ You’re performing a single operation.
+ Your CDK app changes frequently.
+ You want simpler code and don’t need to prioritze Toolkit operation speed.

**Important**  
Most Toolkit interactions should use a cached assembly for better performance. The only time to avoid caching is when your source changes frequently and checking for changes would be expensive.

### How to create, cache, and reuse cloud assemblies
<a name="toolkit-library-configure-ca-cache-how"></a>

After you create a cloud assembly source, you can generate a cloud assembly by synthesizing it. A cloud assembly contains the AWS CloudFormation templates and assets needed for deployment.

We recommend that you generate a cloud assembly once and reuse it for multiple Toolkit operations. This caching approach is more efficient than regenerating the assembly for each operation. Consider regenerating the assembly only when your source changes frequently.

Here’s how to create a cached cloud assembly:

```
// Generate a cloud assembly from your source
const cloudAssembly = await toolkit.synth(cloudAssemblySource);
```

You can then perform various Toolkit actions on the cached cloud assembly, such as `list()`, `deploy()`, and `diff()`. By caching cloud assemblies, subsequent Toolkit actions are performed faster since synthesis occurs only once. For more information, see [synth - Generate cloud assemblies](toolkit-library-actions.md#toolkit-library-actions-synth).

### Dispose of cloud assembly resources
<a name="toolkit-library-configure-ca-cache-dispose"></a>

Always dispose of cloud assemblies when you’re done using them to clean up temporary resources. We recommend using a try/finally block to ensure proper cleanup, especially when performing multiple operations:

```
// Generate a cloud assembly
const cloudAssembly = await toolkit.synth(cloudAssemblySource);

try {
    // Use the cloud assembly for multiple operations
    await toolkit.list(cloudAssembly);
    await toolkit.deploy(cloudAssembly);
} finally {
    // Always dispose when done
    await cloudAssembly.dispose();
}
```

Here’s an example showing how to create and dispose of a cached cloud assembly:

```
import { Toolkit } from '@aws-cdk/toolkit-lib';

const toolkit = new Toolkit();

// Create cloud assembly source from a CDK app
const cloudAssemblySource = await toolkit.fromCdkApp("ts-node app.ts");

// Create cloud assembly from source
const cloudAssembly = await toolkit.synth(cloudAssemblySource);

try {
    // List stacks in the assembly
    await toolkit.list(cloudAssembly);

    // Check for changes
    await toolkit.diff(cloudAssembly);

    // Deploy if needed
    await toolkit.deploy(cloudAssembly);
} finally {
    // Always dispose when done
    await cloudAssembly.dispose();
}
```

### Understanding cloud assembly lifetimes
<a name="toolkit-library-configure-ca-cache-lifetime"></a>

When you create a cached cloud assembly using `synth()`, you get a special type that serves as both a readable `CloudAssembly` and a `CloudAssemblySource`. Any cloud assemblies produced from this cached assembly (for example, from list or deploy operations) are tied to the parent’s lifetime:
+ Only the parent’s dispose() call actually cleans up resources
+ Cloud assemblies from list/deploy operations are managed by their parent
+ Failing to dispose of a cached cloud assembly is considered a bug

## Best practices for cloud assembly sources
<a name="toolkit-library-configure-ca-best-practices"></a>

When working with cloud assembly sources, consider these best practices:
+  **Choose the right source method**: Select the approach that best fits your workflow and requirements.
+  **Cache cloud assemblies**: Generate a cloud assembly once using `synth()` and reuse it for multiple operations to avoid unnecessary synthesis, especially for large applications.
+  **Error handling**: Implement basic error handling to catch and display errors to users. Keep error handling simple and focus on providing clear error messages.
+  **Version compatibility**: Ensure that your CDK Toolkit Library version can support the cloud assemblies you’re working with. If the Construct Library used to create the cloud assembly is newer than what your Toolkit Library supports, you’ll receive an error.
+  **Environment variables**: Be aware that certain environment variables can affect cloud assembly synthesis and deployment. Variables like `CDK_DEFAULT_ACCOUNT`, `CDK_DEFAULT_REGION`, `CDK_OUTDIR`, and `CDK_CONTEXT_JSON` can override default behaviors. Ensure these are set appropriately for your deployment environment.

The following example demonstrates how to implement error handling and proper cleanup while reusing a cloud assembly for multiple operations:

```
import { Toolkit } from '@aws-cdk/toolkit-lib';

// Example with error handling and proper cleanup
async function deployInfrastructure(): Promise<void> {
    let cloudAssembly;

    try {
        // Generate a cloud assembly once
        cloudAssembly = await toolkit.synth(cloudAssemblySource);

        // Reuse the same cloud assembly for multiple operations
        await toolkit.list(cloudAssembly);    // Uses existing assembly
        await toolkit.deploy(cloudAssembly);   // Uses existing assembly
        await toolkit.diff(cloudAssembly);     // Uses existing assembly
    } catch (error) {
        console.error("Failed to deploy:", error);
    } finally {
        // Always dispose when done
        if (cloudAssembly) {
            await cloudAssembly.dispose();
        }
    }
}

// Call the async function
deployInfrastructure().catch(error => {
    console.error("Deployment failed:", error);
    process.exit(1);
});
```

## Resolving potential issues
<a name="toolkit-library-configure-ca-troubleshooting"></a>

Follow these steps to resolve potential issues with cloud assembly sources:
+  **Install missing dependencies**: Run `npm install` to install required dependencies for your CDK app.
+  **Fix path issues**: Check that paths to CDK apps and assembly directories exist and are accessible.
+  **Resolve version mismatches**: Update your CDK Toolkit Library version to match your CDK app version.
+  **Fix synthesis errors**: Review your CDK app code for syntax errors or invalid configurations.

When errors occur during Toolkit operations, keep error handling simple and focus on providing clear error messages to users. Always dispose of cloud assemblies when you’re done using them. Here’s an example showing basic error handling with proper cleanup:

```
import { Toolkit } from '@aws-cdk/toolkit-lib';

// Example with simple error handling
try {
    // Create the cloud assembly source
    const cloudAssemblySource = await toolkit.fromCdkApp("ts-node app.ts");

    // Synthesize the cloud assembly
    const cloudAssembly = await toolkit.synth(cloudAssemblySource);

    // Use the cloud assembly
    await toolkit.list(cloudAssembly);
} catch (error) {
    // Display the error message
    console.error("Operation failed:", error.message);
} finally {
    // Clean up resources
    await cloudAssembly.dispose();
}
```

# Configuring CDK Toolkit messages and interactions
<a name="toolkit-library-configure-messages"></a>

The AWS CDK Toolkit Library provides the ` [IIoHost](https://docs.aws.amazon.com/cdk/api/toolkit-lib/Package/toolkit-lib/Interface/IIoHost/) ` interface to customize how messages and interactions are handled during CDK operations, enabling you to control the display of deployment progress, error messages, and user prompts to better integrate with your application’s user experience.

Before performing operations like deployment or synthesis, you need to understand how the CDK Toolkit communicates with users. The `IIoHost` interface serves as the communication channel between the CDK Toolkit and your application, handling both outgoing messages and incoming user responses.

When the CDK Toolkit runs operations, it communicates through two primary mechanisms:
+  **Messages**: Informational outputs that notify you about operation progress (like "Starting deployment" or "Resource created").
+  **Requests**: Decision points that require input or confirmation (like "Do you want to deploy these changes?"), giving you an opportunity to provide information that wasn’t known to be needed beforehand.

## Using the `IIoHost` interface
<a name="toolkit-library-configure-messages-iiohost"></a>

The `IIoHost` interface consists of two primary methods:

1.  `notify`: Handles one-way informational messages.

1.  `requestResponse`: Handles interactive requests that require a response.

```
import { IoMessage, IoRequest } from '@aws-cdk/toolkit-lib';

interface IIoHost {
  // Handle informational messages
  notify(message: IoMessage): Promise<void>;

  // Handle requests that need responses
  requestResponse(request: IoRequest): Promise<any>;
}
```

## Message levels and request types
<a name="toolkit-library-configure-messages-levels"></a>

The CDK Toolkit generates several types of messages and requests:

### Message levels
<a name="_message_levels"></a>
+  **Debug**: Detailed messages for troubleshooting.
+  **Error**: Error messages that may affect operation.
+  **Info**: General informational messages.
+  **Result** - Primary message of an operation.
+  **Trace**: Very detailed execution flow information.
+  **Warning**: Warning messages that don’t prevent operation.

For a complete list, see [IoMessages Registry](https://docs.aws.amazon.com/cdk/api/toolkit-lib/message-registry/) in the * AWS CDK Toolkit Library API Reference*.

### Request types
<a name="_request_types"></a>

The CDK Toolkit sends requests when it needs input or confirmation from the user. These are special messages that allow for a response. If no response is provided, the Toolkit will use a default response when available.

## Basic `IIoHost` implementation
<a name="toolkit-library-configure-messages-basic"></a>

Here’s a simple example of implementing a custom io host:

```
import { Toolkit } from '@aws-cdk/toolkit-lib';

// Create a toolkit with custom message handling
const toolkit = new Toolkit({
  ioHost: {
    // Implementing the IIoHost interface
    // Handle informational messages
    notify: async function (msg) {
      // Example: Handle different message levels appropriately
      switch (msg.level) {
        case 'error':
          console.error(`[${msg.time}] ERROR: ${msg.message}`);
          break;
        case 'warning':
          console.warn(`[${msg.time}] WARNING: ${msg.message}`);
          break;
        case 'info':
          console.info(`[${msg.time}] INFO: ${msg.message}`);
          break;
        case 'debug':
          console.debug(`[${msg.time}] DEBUG: ${msg.message}`);
          break;
        case 'trace':
          console.debug(`[${msg.time}] TRACE: ${msg.message}`);
          break;
        default:
          console.log(`[${msg.time}] ${msg.level}: ${msg.message}`);
      }
    },

    // Handle requests that need responses
    requestResponse: async function (msg) {
      // Example: Log the request and use default response
      console.log(`Request: ${msg.message}, using default: ${msg.defaultResponse}`);
      return msg.defaultResponse;

      // Or implement custom logic to provide responses
      // if (msg.type === 'deploy') {
      //   return promptUserForDeployment(msg);
      // }
    }
  } as IIoHost // Explicitly cast to IIoHost interface
});
```

The CDK Toolkit awaits the completion of each call, allowing you to perform asynchronous operations like HTTP requests or user prompts when handling messages.

## Default `IIoHost` behavior
<a name="toolkit-library-configure-messages-iiohost-default"></a>

If you don’t provide a custom io host, the CDK Toolkit Library uses a default non-interactive implementation:
+ Console output for messages (using appropriate colors for different message types).
+ Fully non-interactive with no prompts for user input.
+ Automatically uses default responses where possible (equivalent to answering "yes" to prompts).
+ Fails when input is required but no default response is available.

This default behavior is suitable for unattended operations, but not for interactive command-line applications. For command-line applications that require user interaction, you’ll need to implement a custom io host. Custom implementations are also useful for integrating with logging systems, UIs, or other specialized environments.

## Advanced io host implementation
<a name="toolkit-library-configure-messages-advanced"></a>

For more complex scenarios, we recommend extending the `NonInteractiveIoHost` class as a starting point. This approach allows you to leverage the existing non-interactive implementation while customizing only the specific behaviors you need to change.

Here’s an example of a custom io host that extends the base implementation:

```
import { NonInteractiveIoHost } from '@aws-cdk/toolkit-lib';

class MyCustomIoHost extends NonInteractiveIoHost {
  // Override only the methods you need to customize

  // Example: Custom implementation for notify
  public async notify(msg: IoMessage<unknown>): Promise<void> {
    // Add custom notification handling logic
    if (msg.level === 'error') {
      console.error(`ERROR: ${msg.message}`);
      // Optionally log to a service or notify a monitoring system
      await this.logToMonitoringService(msg);
    } else {
      await super.notify(msg);
    }
  }

  // Example: Custom implementation for requestResponse
  public async requestResponse<T, U>(request: IoRequest<T, U>): Promise<U> {
    // Implement custom request handling
    console.log(`Received request: ${request.message}`);
    return request.defaultResponse;
  }

  private async logToMonitoringService(msg: IoMessage<unknown>): Promise<void> {
    // Implementation for monitoring service integration
    console.log(`Logging to monitoring service: ${msg.level} - ${msg.message}`);
  }
}
```

This approach is more maintainable than implementing the entire `IIoHost` interface from scratch, as you only need to override the specific methods that require custom behavior.

## Integrating with different environments
<a name="toolkit-library-configure-messages-integration"></a>

### Web application integration
<a name="_web_application_integration"></a>

```
import { Toolkit } from '@aws-cdk/toolkit-lib';

// Example for integrating with a web application
const toolkit = new Toolkit({
  ioHost: {
    notify: async function (msg) {
      // Send message to frontend via WebSocket
      webSocketServer.send(JSON.stringify({
        type: 'cdk-notification',
        messageLevel: msg.level,
        message: msg.message,
        time: msg.time
      }));
    },

    requestResponse: async function (msg) {
      // Create a promise that will be resolved when the user responds
      return new Promise((resolve) => {
        const requestId = generateUniqueId();

        // Store the resolver function
        pendingRequests[requestId] = resolve;

        // Send request to frontend
        webSocketServer.send(JSON.stringify({
          type: 'cdk-request',
          requestId: requestId,
          requestType: msg.type,
          message: msg.message,
          defaultResponse: msg.defaultResponse
        }));

        // Frontend would call an API endpoint with the response,
        // which would then call pendingRequests[requestId](response)
      });
    }
  } as IIoHost // Explicitly cast to IIoHost interface
});
```

### CI/CD environment integration
<a name="_cicd_environment_integration"></a>

```
import { Toolkit } from '@aws-cdk/toolkit-lib';

// Example for CI/CD environments (non-interactive)
const toolkit = new Toolkit({
  ioHost: {
    notify: async function (msg) {
      // Log all messages with appropriate level
      switch (msg.level) {
        case 'error':
          console.error(msg.message);
          break;
        case 'warning':
          console.warn(msg.message);
          break;
        default:
          console.log(msg.message);
      }
    },

    requestResponse: async function (msg) {
      // In CI/CD, always use default responses or predefined answers
      console.log(`Auto-responding to request: ${msg.message} with ${msg.defaultResponse}`);
      return msg.defaultResponse;
    }
  } as IIoHost // Explicitly cast to IIoHost interface
});
```

## Best practices for io host implementation
<a name="toolkit-library-configure-messages-best-practices"></a>

When implementing a custom io host, consider these best practices:
+  **Error handling**: Implement robust error handling in your io host methods to prevent failures from affecting CDK operations.
+  **Timeouts**: Consider implementing timeouts for user interactions to prevent indefinite waiting.
+  **Logging**: Store important messages in logs for troubleshooting, especially in non-interactive environments.
+  **Default responses**: Provide sensible default responses for automated environments where user interaction isn’t possible.
+  **Progress indication**: For long-running operations, provide clear progress indicators to improve user experience.

The following example demonstrates these best practices by implementing a custom io host with error handling, timeouts for user interactions, and proper logging. This implementation is suitable for interactive applications where you need to balance user responsiveness with reliable operation:

```
import { Toolkit } from '@aws-cdk/toolkit-lib';

// Example with error handling and timeouts
const toolkit = new Toolkit({
  ioHost: {
    notify: async function (msg) {
      try {
        console.log(`[${msg.time}] ${msg.level}: ${msg.message}`);
        // Additional logging or UI updates
      } catch (error) {
        // Ensure errors in notification handling don't break the CDK operation
        console.error("Error handling notification:", error);
      }
    },

    requestResponse: async function (msg) {
      try {
        // Implement timeout for user response
        const response = await Promise.race([
          getUserResponse(msg),
          new Promise(resolve => setTimeout(() => resolve(msg.defaultResponse), 60000))
        ]);
        return response;
      } catch (error) {
        console.error("Error handling request:", error);
        return msg.defaultResponse;
      }
    }
  } as IIoHost // Explicitly cast to IIoHost interface
});
```

## Troubleshooting
<a name="toolkit-library-configure-messages-troubleshooting"></a>

Considerations when implementing a custom io host:
+  **Unhandled promise rejections**: Ensure all async operations are properly handled with try/catch blocks.
+  **Infinite waiting**: Implement timeouts for all user interactions to prevent the application from hanging.
+  **Missing message levels**: Be prepared to handle new message levels that might be added in future CDK versions.
+  **Inconsistent responses**: Ensure your requestResponse implementation returns values in the expected format.

The following example demonstrates a robust approach to handling message levels, including graceful handling of unknown message types that might be introduced in future CDK versions. This implementation ensures your io host remains compatible with CDK updates while maintaining proper logging:

```
import { Toolkit } from '@aws-cdk/toolkit-lib';

// Example of handling unknown message levels
const toolkit = new Toolkit({
  ioHost: {
    notify: async function (msg) {
      // Handle known levels
      const knownLevels = ['info', 'warning', 'error', 'debug', 'trace', 'status'];

      if (knownLevels.includes(msg.level)) {
        // Handle known level
        handleKnownMessageLevel(msg);
      } else {
        // Handle unknown level as info
        console.log(`Unknown message level "${msg.level}": ${msg.message}`);
      }
    },

    requestResponse: async function (msg) {
      // Default implementation
      return msg.defaultResponse;
    }
  } as IIoHost // Explicitly cast to IIoHost interface
});
```

# Advanced CDK Toolkit Library examples
<a name="toolkit-library-examples"></a>

Learn how to use advanced features of the AWS CDK Toolkit Library through practical examples. This guide provides detailed code samples for error handling, deployment monitoring, and cloud assembly management that build upon the basic concepts covered in other sections.

## Integrating features
<a name="toolkit-library-examples-integration"></a>

The following example demonstrates how to combine cloud assembly sources, custom io host implementation, and deployment options:

```
import { Toolkit, StackSelectionStrategy, IIoHost } from '@aws-cdk/toolkit-lib';

async function deployApplication(appPath, environment, options = {}) {
  // Create toolkit with custom message handling
  const toolkit = new Toolkit({
    ioHost: {
      notify: async (msg) => {
        // Add environment to all messages
        console.log(`[${environment}][${msg.time}] ${msg.level}: ${msg.message}`);
      },
      requestResponse: async (msg) => {
        // In production environments, use default responses
        if (environment === 'production') {
          console.log(`Auto-approving for production: ${msg.message}`);
          return msg.defaultResponse;
        }

        // For other environments, implement custom approval logic
        return promptForApproval(msg);
      }
    } as IIoHost
  });

  try {
    // Create cloud assembly source from the CDK app
    console.log(`Creating cloud assembly source from ${appPath}`);
    const cloudAssemblySource = await toolkit.fromCdkApp(appPath);

    // Synthesize the cloud assembly
    console.log(`Synthesizing cloud assembly`);
    const cloudAssembly = await toolkit.synth(cloudAssemblySource);

    try {
      // Deploy with environment-specific options
      console.log(`Deploying to ${environment} environment`);
      return await toolkit.deploy(cloudAssembly, {
        stacks: options.stacks || { strategy: StackSelectionStrategy.ALL_STACKS },
        parameters: options.parameters || {},
        tags: {
          Environment: environment,
          DeployedBy: 'CDK-Toolkit-Library',
          DeployTime: new Date().toISOString()
        }
      });
    } finally {
      // Always dispose when done
      await cloudAssembly.dispose();
    }
  } catch (error) {
    console.error(`Deployment to ${environment} failed:`, error);
    throw error;
  }
}

// Example usage
await deployApplication('ts-node app.ts', 'staging', {
  parameters: {
    MyStack: {
      InstanceType: 't3.small'
    }
  }
});
```

## Tracking deployment progress
<a name="toolkit-library-examples-progress"></a>

Track deployment progress with detailed status updates:

```
import { Toolkit, StackSelectionStrategy, IIoHost } from '@aws-cdk/toolkit-lib';

// Create a progress tracker
class DeploymentTracker {
  private startTime: Date;
  private resources = new Map<string, string>();

  constructor() {
    this.startTime = new Date();
  }

  onStackEvent(stackName: string, event: string, timestamp: string) {
    // Calculate elapsed time if needed, or use the provided timestamp
    const elapsed = (new Date().getTime() - this.startTime.getTime()) / 1000;
    console.log(`[${timestamp}] (${elapsed.toFixed(1)}s elapsed) Stack ${stackName}: ${event}`);
  }

  onResourceEvent(resourceId: string, status: string) {
    this.resources.set(resourceId, status);
    this.printProgress();
  }

  private printProgress() {
    console.log('\nResource Status:');
    for (const [id, status] of this.resources.entries()) {
      console.log(`- ${id}: ${status}`);
    }
    console.log();
  }
}

// Use the tracker with the toolkit
const tracker = new DeploymentTracker();
const toolkit = new Toolkit({
  ioHost: {
    notify: async (msg) => {
      if (msg.code.startsWith('CDK_DEPLOY')) {
        // Track deployment events
        if (msg.data && 'stackName' in msg.data) {
          tracker.onStackEvent(msg.data.stackName, msg.message, msg.time);
        }
      } else if (msg.code.startsWith('CDK_RESOURCE')) {
        // Track resource events
        if (msg.data && 'resourceId' in msg.data) {
          tracker.onResourceEvent(msg.data.resourceId, msg.message);
        }
      }
    }
  } as IIoHost
});

// Example usage with progress tracking
async function deployWithTracking(cloudAssemblySource: any) {
  try {
    // Synthesize the cloud assembly
    const cloudAssembly = await toolkit.synth(cloudAssemblySource);

    try {
      // Deploy using the cloud assembly
      await toolkit.deploy(cloudAssembly, {
        stacks: {
          strategy: StackSelectionStrategy.ALL_STACKS
        }
      });
    } finally {
      // Always dispose when done
      await cloudAssembly.dispose();
    }
  } catch (error) {
    // Display the error message
    console.error("Operation failed:", error.message);
    throw error;
  }
}
```

## Handling errors with recovery
<a name="toolkit-library-examples-error"></a>

Implement robust error handling with recovery strategies:

```
import { Toolkit, ToolkitError, StackSelectionStrategy } from '@aws-cdk/toolkit-lib';

async function deployWithRetry(toolkit: Toolkit, cloudAssemblySource: any) {
  try {
    // Synthesize the cloud assembly
    const cloudAssembly = await toolkit.synth(cloudAssemblySource);

    try {
      // Deploy using the cloud assembly
      await toolkit.deploy(cloudAssembly, {
        stacks: {
          strategy: StackSelectionStrategy.ALL_STACKS
        }
      });
    } finally {
      // Always dispose when done
      await cloudAssembly.dispose();
    }
  } catch (error) {
    // Simply show the error to the user
    console.error("Operation failed:", error.message);
    throw error;
  }
}

// Example usage
try {
  await deployWithRetry(toolkit, cloudAssemblySource);
} catch (error) {
  console.error("Operation failed:", error.message);
  process.exit(1);
}
```

## Integrating with CI/CD pipelines
<a name="toolkit-library-examples-cicd"></a>

Integrate the CDK Toolkit Library into a CI/CD pipeline:

```
import { Toolkit, StackSelectionStrategy, IIoHost } from '@aws-cdk/toolkit-lib';
import * as fs from 'fs';
import * as path from 'path';

async function cicdDeploy() {
  // Create a non-interactive toolkit for CI/CD environments
  const toolkit = new Toolkit({
    ioHost: {
      notify: async (msg) => {
        // Write to both console and log file
        const logMessage = `${msg.time} [${msg.level}] ${msg.message}`;
        console.log(logMessage);

        // Append to deployment log file
        fs.appendFileSync('deployment.log', logMessage + '\n');
      },
      requestResponse: async (msg) => {
        // Always use default responses in CI/CD
        console.log(`Auto-responding to: ${msg.message} with: ${msg.defaultResponse}`);
        return msg.defaultResponse;
      }
    } as IIoHost
  });

  // Determine environment from CI/CD variables
  const environment = process.env.DEPLOYMENT_ENV || 'development';

  // Load environment-specific parameters
  const paramsPath = path.join(process.cwd(), `params.${environment}.json`);
  const parameters = fs.existsSync(paramsPath)
    ? JSON.parse(fs.readFileSync(paramsPath, 'utf8'))
    : {};

  try {
    // Use pre-synthesized cloud assembly from build step
    const cloudAssemblySource = await toolkit.fromAssemblyDirectory('cdk.out');

    // Synthesize the cloud assembly
    const cloudAssembly = await toolkit.synth(cloudAssemblySource);

    try {
      // Deploy with CI/CD specific options
      const result = await toolkit.deploy(cloudAssembly, {
        stacks: { strategy: StackSelectionStrategy.ALL_STACKS },
        parameters,
        tags: {
          Environment: environment,
          BuildId: process.env.BUILD_ID || 'unknown',
          CommitHash: process.env.COMMIT_HASH || 'unknown'
        }
      });

      // Write outputs to a file for subsequent pipeline steps
      fs.writeFileSync(
        'stack-outputs.json',
        JSON.stringify(result.outputs, null, 2)
      );

      return result;
    } finally {
      // Always dispose when done
      await cloudAssembly.dispose();
    }
  } catch (error) {
    // Display the error message
    console.error("Operation failed:", error.message);
    process.exit(1);
  }
}

// Run the CI/CD deployment
cicdDeploy().then(() => {
  console.log('CI/CD deployment completed successfully');
});
```

## Additional resources
<a name="toolkit-library-examples-resources"></a>

For more detailed information on specific components used in these examples, refer to:
+  [Managing cloud assembly sources](toolkit-library-configure-ca.md) - Learn how to create and manage cloud assembly sources.
+  [Configuring messages and interactions](toolkit-library-configure-messages.md) - Detailed guide on customizing the `IIoHost` interface.