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

# remote — Cross-Repo Stack References

> Consume outputs from a stack in another repository using typed remote references.

At scale, platform engineering is a multi-repo discipline. The networking team owns the VPC and subnets. The security team owns IAM roles and KMS keys. The platform team owns the EKS cluster. Each lives in its own repository, its own stack, its own apply pipeline. But application stacks need all of these — they need the VPC ID to place resources, the IAM role ARN to grant permissions, the cluster endpoint to deploy workloads. Without a mechanism for cross-repo output consumption, teams copy-paste values, hard-code ARNs, or maintain sprawling config files that drift out of date. The `remote` block solves this: it declares a dependency on another stack's outputs, and `@remotename.output_name` references consume those outputs as `Pending<T>` values — always up-to-date, always type-checked, never copy-pasted.

## What you'll learn

* How `remote` declares a cross-repo stack dependency
* The `@name.output` reference syntax for consuming remote outputs
* What `ubx validate` checks vs what requires the remote stack to exist

***

## Why this matters

<Info>
  `remote` references compile to Pulumi `StackReference` objects — the same mechanism Pulumi uses natively for cross-stack communication. ubx wraps this with compile-time type checking: if the interface contract is declared (tutorial 35), referencing a non-existent output is a compile error, not a runtime surprise.
</Info>

***

## The source code

<CodeGroup>
  ```hcl main.iac theme={"theme":"css-variables"}
  # @platform.vpc_id is a RemoteRef — always Pending<T>.
  # Compiles to: platform.getOutput("vpc_id")
  unit "aws_security_group" "app" {
    name        = "myapp-${input.env}-sg"
    description = "App tier security group"
    vpc_id      = @platform.vpc_id
  }

  unit "aws_rds_instance" "db" {
    engine                 = "postgres"
    instance_class         = "db.t3.micro"
    identifier             = "myapp-${input.env}"
    vpc_security_group_ids = [unit.aws_security_group.app.id]
  }
  ```

  ```hcl remotes.iac theme={"theme":"css-variables"}
  # remote "name" { source, stack } declares a cross-repo stack dependency.
  # Compiles to: const platform = new pulumi.StackReference("org/repo/stack")
  remote "platform" {
    source = "github.com/myorg/platform//stacks/networking"
    stack  = "${input.env}-networking"
  }
  ```

  ```hcl inputs.iac theme={"theme":"css-variables"}
  input "env" {
    type    = "string"
    default = "prod"
  }
  ```

  ```hcl outputs.iac theme={"theme":"css-variables"}
  output "db_endpoint" {
    value = unit.aws_rds_instance.db.endpoint
  }
  ```

  ```hcl ubx.iac theme={"theme":"css-variables"}
  ubx {
    name    = "remote-stack-reference"
    runtime = "typescript"
    stacks  = ["dev", "staging", "prod"]
  }

  backend "s3" {
    bucket = "my-ubx-state"
    region = "us-east-1"
    key    = "${stack}/remote-stack-reference.tfstate"
  }
  ```
</CodeGroup>

***

## How it works

<Steps>
  <Step title="remote compiles to a Pulumi StackReference">
    `remote "platform" { source = "...", stack = "prod-networking" }` compiles to `new pulumi.StackReference("org/platform/prod-networking")` in TypeScript. Pulumi's StackReference reads the remote stack's outputs from its state backend.
  </Step>

  <Step title="@name.output compiles to getOutput()">
    `@platform.vpc_id` compiles to `platform.getOutput("vpc_id")`, which returns a `pulumi.Output<unknown>`. ubx wraps this with the declared type from the interface contract (if present) for type-safe downstream use.
  </Step>

  <Step title="ubx validate checks syntax; the remote stack must exist for plan/apply">
    `ubx validate` confirms the `remote` block's syntax and that `@platform.xxx` references are syntactically valid. It doesn't contact the remote stack's backend or verify its outputs exist. `ubx plan` and `ubx apply` require the remote stack to have been applied and its state to be accessible.
  </Step>
</Steps>

***

## What ubx generates

<CodeGroup>
  ```typescript index.ts theme={"theme":"css-variables"}
  // Generated by ubx — do not edit
  import * as pulumi from "@pulumi/pulumi";
  import * as aws from "@pulumi/aws";

  const config = new pulumi.Config();
  const env = config.get("env") || "prod";

  // remote block → StackReference
  const platform = new pulumi.StackReference(`myorg/platform/${env}-networking`);

  // @platform.vpc_id → platform.getOutput("vpc_id")
  const appSg = platform.getOutput("vpc_id").apply(vpcId =>
      new aws.ec2.SecurityGroup("app", {
          name: `myapp-${env}-sg`,
          description: "App tier security group",
          vpcId: vpcId as string,
      })
  );

  const db = appSg.apply(sg =>
      new aws.rds.Instance("db", {
          engine: "postgres",
          instanceClass: "db.t3.micro",
          identifier: `myapp-${env}`,
          vpcSecurityGroupIds: [sg.id],
      })
  );

  export const dbEndpoint = db.apply(d => d.endpoint);
  ```

  ```python __main__.py theme={"theme":"css-variables"}
  # Generated by ubx — do not edit
  import pulumi
  import pulumi_aws as aws

  config = pulumi.Config()
  env = config.get("env") or "prod"

  platform = pulumi.StackReference(f"myorg/platform/{env}-networking")

  vpc_id = platform.get_output("vpc_id")

  app_sg = vpc_id.apply(lambda vpc_id:
      aws.ec2.SecurityGroup("app",
          name=f"myapp-{env}-sg",
          description="App tier security group",
          vpc_id=vpc_id,
      )
  )

  db = app_sg.apply(lambda sg:
      aws.rds.Instance("db",
          engine="postgres", instance_class="db.t3.micro",
          identifier=f"myapp-{env}",
          vpc_security_group_ids=[sg.id],
      )
  )

  pulumi.export("db_endpoint", db.apply(lambda d: d.endpoint))
  ```

  ```go main.go theme={"theme":"css-variables"}
  // Generated by ubx — do not edit
  package main

  import (
      "fmt"
      "github.com/pulumi/pulumi-aws/sdk/v6/go/aws/ec2"
      "github.com/pulumi/pulumi-aws/sdk/v6/go/aws/rds"
      "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
      "github.com/pulumi/pulumi/sdk/v3/go/pulumi/config"
  )

  func main() {
      pulumi.Run(func(ctx *pulumi.Context) error {
          cfg := config.New(ctx, "")
          env := cfg.Get("env")
          if env == "" { env = "prod" }

          platform, err := pulumi.NewStackReference(ctx, fmt.Sprintf("myorg/platform/%s-networking", env), nil)
          if err != nil { return err }

          vpcId := platform.GetOutput(pulumi.String("vpc_id"))

          _ = vpcId.ApplyT(func(id interface{}) (*ec2.SecurityGroup, error) {
              return ec2.NewSecurityGroup(ctx, "app", &ec2.SecurityGroupArgs{
                  Name: pulumi.Sprintf("myapp-%s-sg", env),
                  Description: pulumi.String("App tier security group"),
                  VpcId: pulumi.String(id.(string)),
              })
          })

          ctx.Export("dbEndpoint", pulumi.String("resolved at apply"))
          return nil
      })
  }
  ```
</CodeGroup>

***

## Common mistakes

<Warning>
  `remote` stack outputs are untyped by default — `platform.getOutput("vpc_id")` returns `pulumi.Output<unknown>`. Without an `interface` contract (tutorial 35), you get no compile-time check that `vpc_id` actually exists in the remote stack. Reference an output that doesn't exist and you'll get `undefined` at apply time, not a compile error. Add an `interface` contract to the remote stack for type safety.
</Warning>

<Tip>
  The `stack` attribute supports string interpolation — `stack = "${input.env}-networking"` is valid and the standard pattern for environment-specific remote stack references. This ensures the right stack is referenced for each environment without duplicating the `remote` block.
</Tip>

***

## Run it

```bash theme={"theme":"css-variables"}
ubx validate              # syntax check — does not contact remote stack
ubx plan                  # requires remote stack to be applied and accessible
ubx apply                 # reads remote outputs at apply time
```

***

## What you learned

<Check>`remote` compiles to a Pulumi `StackReference` — outputs are consumed with `@name.output`</Check>
<Check>`ubx validate` checks syntax only; `ubx plan` requires the remote stack to exist and be accessible</Check>
<Check>Add an `interface` contract to the remote stack for compile-time type safety on output references</Check>

***

## Next steps

<CardGroup cols={2}>
  <Card title="interface contract validation" href="/v1/tutorials/35-interface-contract-validation">
    Declare typed output contracts for cross-stack safety
  </Card>

  <Card title="remote block reference" href="/v1/language/remote">
    Full remote block syntax and options
  </Card>
</CardGroup>

***

<Info>
  Full runnable example: [github.com/ubiquex/ubx-examples/34-remote-stack-reference](https://github.com/ubiquex/ubx-examples/tree/main/34-remote-stack-reference)
</Info>
