> ## 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.

# Pulumi Plugin

> The official Pulumi engine plugin — generates Python, TypeScript, or Go programs and runs them via the Pulumi Automation API.

The `ubx-plugin-pulumi` plugin is the primary execution engine for ubx. It takes IR JSON, generates a complete Pulumi program in your chosen runtime language, and runs it via the Pulumi Automation API.

## Install

```bash theme={"theme":"css-variables","languages":{"custom":["/languages/xcl.json"]}}
ubx plugin install pulumi
```

Installs to `~/.ubx/plugins/pulumi/ubx-plugin-pulumi`.

## Configure

In `workspace.xcl`:

```xcl theme={"theme":"css-variables","languages":{"custom":["/languages/xcl.json"]}}
workspace {
  engine  = "pulumi"
  runtime = "python"   // python | typescript | go
}
```

## What the plugin generates

### Python runtime (`runtime = "python"`)

```
.ubx/
├── __main__.py        # Pulumi Python program
├── requirements.txt   # Dependencies
└── Pulumi.yaml        # Project metadata
```

`requirements.txt` always starts with:

```
pulumi>=3.0.0,<4.0.0
```

Then adds per-provider packages:

```
pulumi-aws>=1.0.0
pulumi-kubernetes>=1.0.0
```

### TypeScript runtime (`runtime = "typescript"`)

```
.ubx/
├── index.ts
├── package.json
└── Pulumi.yaml
```

### Go runtime (`runtime = "go"`)

```
.ubx/
├── main.go
├── go.mod
└── Pulumi.yaml
```

## Stack name

The Pulumi project/stack name is derived from the stack directory name:

```xcl theme={"theme":"css-variables","languages":{"custom":["/languages/xcl.json"]}}
stackName = filepath.Base(dir)
```

## Cross-stack references

`@stack.output` references become Pulumi `StackReference` objects in generated code:

```python theme={"theme":"css-variables","languages":{"custom":["/languages/xcl.json"]}}
# Generated for @networking.vpc_id
networking_ref = pulumi.StackReference(
    f"{pulumi.get_organization()}/{pulumi.get_project()}/networking"
)
vpc_id = networking_ref.get_output("vpc_id")
```

## Outputs

XCL `output` blocks become `pulumi.export()` calls:

```python theme={"theme":"css-variables","languages":{"custom":["/languages/xcl.json"]}}
# XCL: output vpc_id { value = vpc.id }
pulumi.export("vpc_id", vpc.id)
```

The export key matches the bare identifier in the `output` block label.

## Plugin RPCs

| RPC       | Description                                              |
| --------- | -------------------------------------------------------- |
| `Compile` | Generates code, returns `artifact_uri` (path to `.ubx/`) |
| `Plan`    | Runs `pulumi preview`, returns summary                   |
| `Apply`   | Runs `pulumi up`, streams `ProgressEvent`                |
| `Destroy` | Runs `pulumi destroy`, streams `ProgressEvent`           |

## Backend

The plugin receives the backend URL from the IR. Backend URL construction:

| Backend type | URL format                       |
| ------------ | -------------------------------- |
| `local`      | `file://<stack-dir>/.ubx/state/` |
| `s3`         | `s3://bucket/key`                |
| `gcs`        | `gs://bucket`                    |
| `azblob`     | `azblob://container`             |
| `pulumi`     | `https://api.pulumi.com`         |

## For-loop resources

For `for`-iterated resources, the plugin generates list comprehensions in Python:

```python theme={"theme":"css-variables","languages":{"custom":["/languages/xcl.json"]}}
# XCL: subnets = aws.ec2.Subnet { for az in input.azs ... }
subnets = [aws.ec2.Subnet(f"subnet-{i}", ...) for i, az in enumerate(azs)]
```

Outputs are collected as:

```python theme={"theme":"css-variables","languages":{"custom":["/languages/xcl.json"]}}
pulumi.export("subnet_ids", [s.id for s in subnets])
```
