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

# Runtimes

> ubx compiles .iac files to TypeScript (default), Python, or Go — all from the same source and the same IR.

ubx supports three Pulumi runtimes. Every `.iac` file you write compiles to the same semantics regardless of which runtime you choose; only the generated language changes.

## Choosing a runtime

Set the `runtime` key in `ubx.yaml`:

```yaml theme={"theme":"css-variables"}
name: my-platform
backend: file://.ubx/state
stacks: [dev, staging, prod]

runtime: typescript   # default — can be omitted
# runtime: python
# runtime: go
```

If `runtime` is omitted, ubx defaults to `typescript`.

## Generated files per runtime

| Runtime      | Files generated                             | Pulumi.yaml `runtime` |
| ------------ | ------------------------------------------- | --------------------- |
| `typescript` | `.ubx/index.ts`, `.ubx/package.json`        | `nodejs`              |
| `python`     | `.ubx/__main__.py`, `.ubx/requirements.txt` | `python`              |
| `go`         | `.ubx/main.go`, `.ubx/go.mod`               | `go`                  |

All runtimes also receive `.ubx/Pulumi.yaml` with the correct `runtime:` field so Pulumi knows how to execute the stack.

## TypeScript (default)

TypeScript is the default and most feature-complete target. It supports all ubx language features including `component` blocks with local `.iac` authoring, `for_each`, `count`, `when`, and all five `secret()` backends.

```hcl theme={"theme":"css-variables"}
input "env" {}

unit "aws_s3_bucket_v2" "bucket" {
  bucket = "${input.env}-assets"
}

output "bucket_name" {
  value = unit.aws_s3_bucket_v2.bucket.bucket
}
```

Generated `.ubx/index.ts`:

```typescript theme={"theme":"css-variables"}
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const env = new pulumi.Config().require("env");

const bucket = new aws.s3.BucketV2("bucket", {
    bucket: `${env}-assets`,
});

export const bucketName = bucket.bucket;
```

## Python

The Python target generates idiomatic Pulumi Python. Provider packages are imported as `pulumi_aws`, `pulumi_gcp`, `pulumi_azure_native`, etc.

```yaml theme={"theme":"css-variables"}
runtime: python
```

Generated `.ubx/__main__.py`:

```python theme={"theme":"css-variables"}
import pulumi
import pulumi_aws as aws

config = pulumi.Config()
env = config.require("env")

bucket = aws.s3.BucketV2("bucket",
    bucket=f"{env}-assets",
)

pulumi.export("bucket_name", bucket.bucket)
```

Generated `.ubx/requirements.txt`:

```
pulumi>=3.0.0,<4.0.0
pulumi-aws>=6.0.0,<7.0.0
```

Provider versions in `requirements.txt` default to the latest major. Use a [`provider` block](/v1/language/provider) to pin a specific version:

```hcl theme={"theme":"css-variables"}
provider "aws" {
  version = "~> 6.0"
}
```

## Go

The Go target generates a single `main.go` with a `pulumi.Run()` entry point and a `go.mod` for the provider dependencies.

```yaml theme={"theme":"css-variables"}
runtime: go
```

Generated `.ubx/main.go`:

```go theme={"theme":"css-variables"}
package main

import (
    "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
    "github.com/pulumi/pulumi/sdk/v3/go/pulumi/config"

    "github.com/pulumi/pulumi-aws/sdk/v6/go/aws/s3"
)

func main() {
    pulumi.Run(func(ctx *pulumi.Context) error {
        cfg := config.New(ctx, "")

        env := cfg.Require("env")

        bucket, err := s3.NewBucketV2(ctx, "bucket", &s3.BucketV2Args{
            Bucket: pulumi.String(fmt.Sprintf("%s-assets", env)),
        })
        if err != nil {
            return err
        }

        ctx.Export("bucket_name", bucket.Bucket)

        return nil
    })
}
```

Generated `.ubx/go.mod`:

```
module infra

go 1.21

require (
    github.com/pulumi/pulumi/sdk/v3 v3.0.0
    github.com/pulumi/pulumi-aws/sdk/v6 v6.0.0
)
```

Provider versions in `go.mod` default to the latest major. Use a [`provider` block](/v1/language/provider) to pin a specific version:

```hcl theme={"theme":"css-variables"}
provider "aws" {
  version = "~> 6.2.1"
}
```

This translates `~> 6.2.1` → `v6.2.1` in `go.mod`.

## Pending\<T> compilation per runtime

References to resource outputs (`unit.name.attr`, `component.name.output`, `@stack.output`) resolve at apply time and have type `Pending<T>`. Each runtime compiles them differently:

### TypeScript

Single pending ref:

```typescript theme={"theme":"css-variables"}
const copy = src.bucket.apply(srcBucket =>
    new aws.s3.BucketV2("copy", { bucket: srcBucket })
);
```

Multiple pending refs:

```typescript theme={"theme":"css-variables"}
const merged = pulumi.all([a.bucket, b.tagsAll]).apply(([aBucket, bTagsAll]) =>
    new aws.s3.BucketV2("merged", { bucket: aBucket, tagsAll: bTagsAll })
);
```

### Python

Single pending ref:

```python theme={"theme":"css-variables"}
copy = src.bucket.apply(lambda src_bucket:
    aws.s3.BucketV2("copy", bucket=src_bucket)
)
```

Multiple pending refs:

```python theme={"theme":"css-variables"}
merged = pulumi.Output.all(a_bucket=a.bucket, b_tags_all=b.tags_all).apply(
    lambda args: aws.s3.BucketV2("merged",
        bucket=args["a_bucket"],
        tags_all=args["b_tags_all"],
    )
)
```

### Go

Single pending ref:

```go theme={"theme":"css-variables"}
copy := src.Bucket.ApplyT(func(srcBucket string) (*s3.BucketV2, error) {
    return s3.NewBucketV2(ctx, "copy", &s3.BucketV2Args{
        Bucket: pulumi.String(srcBucket),
    })
}).(s3.BucketV2Output)
```

Multiple pending refs:

```go theme={"theme":"css-variables"}
merged := pulumi.All(a.Bucket, b.TagsAll).ApplyT(
    func(args []interface{}) (*s3.BucketV2, error) {
        aBucket := args[0].(string)
        bTagsAll := args[1].(string)
        return s3.NewBucketV2(ctx, "merged", &s3.BucketV2Args{
            Bucket:  pulumi.String(aBucket),
            TagsAll: pulumi.String(bTagsAll),
        })
    },
).(s3.BucketV2Output)
```

## Provider imports per runtime

| Provider     | TypeScript import                               | Python import                         | Go import                                                  |
| ------------ | ----------------------------------------------- | ------------------------------------- | ---------------------------------------------------------- |
| AWS          | `import * as aws from "@pulumi/aws"`            | `import pulumi_aws as aws`            | `github.com/pulumi/pulumi-aws/sdk/v6/go/aws`               |
| GCP          | `import * as gcp from "@pulumi/gcp"`            | `import pulumi_gcp as gcp`            | `github.com/pulumi/pulumi-gcp/sdk/v7/go/gcp`               |
| Azure Native | `import * as azure from "@pulumi/azure-native"` | `import pulumi_azure_native as azure` | `github.com/pulumi/pulumi-azure-native/sdk/v2/go/azure`    |
| Kubernetes   | `import * as k8s from "@pulumi/kubernetes"`     | `import pulumi_kubernetes as k8s`     | `github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes` |
| Datadog      | `import * as datadog from "@pulumi/datadog"`    | `import pulumi_datadog as datadog`    | `github.com/pulumi/pulumi-datadog/sdk/v4/go/datadog`       |

Go sub-packages are derived from the resource type. For `aws_s3_bucket_v2` the import is `...aws/s3` and the constructor is `s3.NewBucketV2`.

## Sensitive outputs per runtime

The `sensitive = true` field on an `output` block wraps the exported value in the runtime's secret wrapper:

| Runtime    | Generated code                |
| ---------- | ----------------------------- |
| TypeScript | `pulumi.secret(value)`        |
| Python     | `pulumi.Output.secret(value)` |
| Go         | `pulumi.ToSecret(value)`      |

## Inputs per runtime

| ubx input    | TypeScript                              | Python                            | Go                              |
| ------------ | --------------------------------------- | --------------------------------- | ------------------------------- |
| No default   | `new pulumi.Config().require("name")`   | `config.require("name")`          | `cfg.Require("name")`           |
| With default | `?? "default"`                          | `config.get("name") or "default"` | `cfg.Get("name")` with fallback |
| Ephemeral    | `pulumi.secret(config.require("name"))` | `config.require_secret("name")`   | `cfg.RequireSecret("name")`     |

## Architecture note

All three runtimes share the same compilation pipeline up through the IR (Intermediate Representation) stage:

```
.iac source
    ↓  parse
    ↓  type-check
    ↓  IR.Build
    ↓
  ┌─────────────────────────────────┐
  │  IRProgram                      │
  └────┬───────────┬───────────┬────┘
       ↓           ↓           ↓
  TypeScript    Python        Go
  index.ts   __main__.py   main.go
```

The IR is the clean boundary between language semantics and emitter syntax. Pending\<T> resolution, lifecycle rules, depends\_on ordering, and all type checking happen once in the IR stage — not per runtime. This guarantees identical behaviour across all three outputs.

## Component Runtime Auto-Detection

When no `runtime` is declared in `ubx.yaml` or the `ubx {}` block, ubx inspects local component source directories and auto-detects the stack runtime. The first component with a recognisable entry-point file sets the runtime for the whole stack:

| Entry-point file | Detected runtime |
| ---------------- | ---------------- |
| `__main__.py`    | Python           |
| `index.ts`       | TypeScript       |
| `main.go`        | Go               |

```hcl theme={"theme":"css-variables"}
ubx {
  name   = "networking"
  stacks = ["dev", "prod"]
  # runtime omitted — auto-detected from components
}

# ubx finds __main__.py in ../components/vpc → uses Python runtime for the whole stack
component "vpc" {
  source = "../components/vpc"
}
```

Stacks with no local `component` blocks, or with only `git::` sources, fall back to TypeScript when no `runtime` is set explicitly.

The stack-level `runtime` key is still supported and takes precedence over auto-detection — set it explicitly when you want to lock the runtime regardless of component contents:

```yaml theme={"theme":"css-variables"}
# ubx.yaml — explicit runtime always wins
runtime: python
```
