> ## Documentation Index
> Fetch the complete documentation index at: https://tfts.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Migrating from CDKTF

> Migrate your CDK for Terraform (CDKTF) projects to tfts

tfts is a drop-in replacement for CDKTF. Migration requires updating imports and regenerating provider bindings.

## Migration Steps

### Step 1: Update Dependencies

Remove CDKTF packages and add tfts:

```bash theme={null}
# Remove CDKTF and pre-built providers
npm remove cdktf cdktf-cli @cdktf/provider-aws @cdktf/provider-google

# Add tfts
npm install tfts
```

### Step 2: Update Core Imports

Change imports from `cdktf` to `tfts`:

```typescript theme={null}
// Before
import { App, TerraformStack, TerraformOutput, TerraformVariable, Fn } from "cdktf";

// After
import { App, TerraformStack, TerraformOutput, TerraformVariable, Fn } from "tfts";
```

### Step 3: Update Provider Imports

CDKTF uses pre-built provider packages (`@cdktf/provider-*`). tfts generates providers locally in `.gen/`.

```typescript theme={null}
// Before (CDKTF pre-built providers)
import { GoogleProvider } from "@cdktf/provider-google/lib/provider";
import { ComputeInstance } from "@cdktf/provider-google/lib/compute-instance";
import * as google from "@cdktf/provider-google";

// After (tfts generated providers - paths relative to your file)
import { GoogleProvider } from "../../../.gen/providers/hashicorp/google/lib/provider/index.js";
import { ComputeInstance } from "../../../.gen/providers/hashicorp/google/lib/compute-instance/index.js";
import * as google from "../../../.gen/providers/hashicorp/google/index.js";
```

Note: The relative path depth (`../../../`) depends on your file's location relative to the project root.

### Step 4: Regenerate Provider Bindings

```bash theme={null}
npx tfts get
```

This reads `cdktf.json` (or `tfts.json`) and generates TypeScript classes in `.gen/`.

### Step 5: Update Configuration (Optional)

Rename `cdktf.json` to `tfts.json` if desired (both are supported):

```bash theme={null}
mv cdktf.json tfts.json
```

## Automated Migration

Save this script as `migrate-from-cdktf.ts` and run with `bun migrate-from-cdktf.ts .`:

```typescript theme={null}
import { existsSync, readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
import { dirname, join, relative, resolve } from "node:path";

function migrateFile(filePath: string, projectRoot: string): { modified: boolean; changes: string[] } {
  const content = readFileSync(filePath, "utf-8");
  let newContent = content;
  const changes: string[] = [];
  const fileDir = dirname(filePath);
  const relToGen = relative(fileDir, join(projectRoot, ".gen"));

  const cdktfCorePattern = /from\s+["']cdktf["']/g;
  if (cdktfCorePattern.test(newContent)) {
    newContent = newContent.replace(cdktfCorePattern, 'from "tfts"');
    changes.push('from "cdktf" -> from "tfts"');
  }

  const constructsPattern = /from\s+["']constructs["']/g;
  if (constructsPattern.test(newContent)) {
    newContent = newContent.replace(constructsPattern, 'from "tfts"');
    changes.push('from "constructs" -> from "tfts"');
  }

  const namespaceImportPattern = /from\s+["']@cdktf\/provider-([^/"']+)["']/g;
  newContent = newContent.replace(namespaceImportPattern, (_, provider) => {
    const newPath = `${relToGen}/providers/hashicorp/${provider}/index.js`;
    changes.push(`@cdktf/provider-${provider} -> ${newPath}`);
    return `from "${newPath}"`;
  });

  const namedImportPattern = /from\s+["']@cdktf\/provider-([^/"']+)\/lib\/([^"']+)["']/g;
  newContent = newContent.replace(namedImportPattern, (_, provider, modulePath) => {
    const newPath = `${relToGen}/providers/hashicorp/${provider}/lib/${modulePath}/index.js`;
    changes.push(`@cdktf/provider-${provider}/lib/${modulePath} -> ${newPath}`);
    return `from "${newPath}"`;
  });

  if (content !== newContent) writeFileSync(filePath, newContent);
  return { modified: content !== newContent, changes };
}

function findTypeScriptFiles(dir: string): string[] {
  const files: string[] = [];
  const skipDirs = new Set(["node_modules", ".gen", "cdktf.out", "dist", ".git"]);
  function walk(currentDir: string) {
    for (const entry of readdirSync(currentDir, { withFileTypes: true })) {
      const fullPath = join(currentDir, entry.name);
      if (entry.isDirectory() && !skipDirs.has(entry.name)) walk(fullPath);
      else if (entry.isFile() && /\.(ts|tsx)$/.test(entry.name)) files.push(fullPath);
    }
  }
  walk(dir);
  return files;
}

const targetDir = resolve(process.argv[2] || ".");
if (!existsSync(targetDir) || !statSync(targetDir).isDirectory()) {
  console.error(`Error: "${targetDir}" is not a valid directory`);
  process.exit(1);
}

console.log(`Migrating CDKTF -> tfts in: ${targetDir}\n`);
const files = findTypeScriptFiles(targetDir);
let totalModified = 0;

for (const file of files) {
  const { modified, changes } = migrateFile(file, targetDir);
  if (modified) {
    totalModified++;
    console.log(file);
    for (const change of changes) console.log(`  ${change}`);
  }
}

console.log(`\n${totalModified} file(s) modified`);
if (totalModified > 0) console.log("\nNext: npx tfts get");
```

The script converts:

* `from "cdktf"` → `from "tfts"`
* `from "constructs"` → `from "tfts"`
* `@cdktf/provider-X` → `{relPath}/.gen/providers/hashicorp/X/index.js`
* `@cdktf/provider-X/lib/Y` → `{relPath}/.gen/providers/hashicorp/X/lib/Y/index.js`

## Import Path Reference

| CDKTF Import                                         | tfts Import                                                                      |
| ---------------------------------------------------- | -------------------------------------------------------------------------------- |
| `from "cdktf"`                                       | `from "tfts"`                                                                    |
| `from "constructs"`                                  | `from "tfts"`                                                                    |
| `from "@cdktf/provider-google"`                      | `from "{relPath}/.gen/providers/hashicorp/google/index.js"`                      |
| `from "@cdktf/provider-google/lib/provider"`         | `from "{relPath}/.gen/providers/hashicorp/google/lib/provider/index.js"`         |
| `from "@cdktf/provider-google/lib/compute-instance"` | `from "{relPath}/.gen/providers/hashicorp/google/lib/compute-instance/index.js"` |
| `from "@cdktf/provider-aws"`                         | `from "{relPath}/.gen/providers/hashicorp/aws/index.js"`                         |
| `from "@cdktf/provider-aws/lib/s3-bucket"`           | `from "{relPath}/.gen/providers/hashicorp/aws/lib/s3-bucket/index.js"`           |

`{relPath}` = relative path from your file to project root (e.g., `../../..` for `src/stacks/my-stack/`)

## API Compatibility

tfts maintains API compatibility with CDKTF core constructs:

| Class                    | Status     |
| ------------------------ | ---------- |
| `App`                    | Compatible |
| `TerraformStack`         | Compatible |
| `TerraformResource`      | Compatible |
| `TerraformDataSource`    | Compatible |
| `TerraformOutput`        | Compatible |
| `TerraformVariable`      | Compatible |
| `TerraformLocal`         | Compatible |
| `TerraformProvider`      | Compatible |
| `Fn`                     | Compatible |
| `TerraformIterator`      | Compatible |
| Backends (S3, GCS, etc.) | Compatible |

## Verification

After migration, verify the generated Terraform JSON is correct:

```bash theme={null}
# Synthesize
npx tfts synth

# Compare output (if you have previous output)
diff -r old-cdktf.out/stacks/my-stack cdktf.out/stacks/my-stack

# Or run terraform plan to check
cd cdktf.out/stacks/my-stack
terraform init
terraform plan
```

## Troubleshooting

### Import Errors

If you see import errors after migration, ensure:

1. You ran `npx tfts get` to generate providers
2. Provider imports use `.js` extension (ESM requirement)
3. Provider paths match the structure in `.gen/`

### Missing Providers

Add any missing providers to your config:

```json theme={null}
{
  "terraformProviders": [
    "hashicorp/google@~>6.0",
    "hashicorp/aws@~>5.0"
  ]
}
```

Then regenerate: `npx tfts get`
