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

# workspace

> The workspace block declares workspace-wide deployment policy that applies to all matching stacks.

The `workspace` block sets workspace-wide defaults for engine, runtime, backend, providers, tags, hooks, plugins, and feature toggles. It applies to every stack in the compilation unit unless a more-specific declaration overrides a field.

Multiple `workspace` blocks may appear across `.xcl` files in the same directory. The blocks are independent — each can carry a `match {}` sub-block to restrict which stacks it applies to. When no `match {}` is present, the block is **universal**: it applies to all stacks.

## Syntax

```xcl theme={"theme":"css-variables"}
workspace {
    name    = "platform"
    engine  = "native"
    runtime = "xcl"
}
```

`workspace` takes no label — there is no quoted string after the keyword. The human-readable name for the workspace comes from the `name` field inside the body.

Only one `backend {}` sub-block is allowed per `workspace {}`. Duplicate backends produce a hard parse error.

## Fields

| Field     | Type   | Default    | Description                   |
| --------- | ------ | ---------- | ----------------------------- |
| `name`    | string | `""`       | Human-readable workspace name |
| `engine`  | string | `"native"` | Execution engine (see below)  |
| `runtime` | string | `"xcl"`    | Codegen runtime (see below)   |

## engine

Controls which execution engine processes the stack.

| Value         | Description                                                                              |
| ------------- | ---------------------------------------------------------------------------------------- |
| `"native"`    | Built-in ubx engine (default)                                                            |
| `"pulumi"`    | Pulumi execution plugin                                                                  |
| `"terraform"` | Terraform execution plugin — **not yet implemented**, produces a hard error at ship time |

## runtime

Controls which code generation target is used.

| Value          | Description                            |
| -------------- | -------------------------------------- |
| `"xcl"`        | XCL native — no codegen step (default) |
| `"python"`     | Pulumi Python                          |
| `"typescript"` | Pulumi TypeScript                      |
| `"go"`         | Pulumi Go                              |

## Valid engine / runtime combinations

Not all engine/runtime pairs are valid. The typechecker enforces these rules:

| engine      | Valid runtimes               |
| ----------- | ---------------------------- |
| `native`    | `xcl` only                   |
| `pulumi`    | `python`, `typescript`, `go` |
| `terraform` | `xcl` only                   |

```xcl theme={"theme":"css-variables"}
// Valid — native engine with xcl runtime
workspace {
    engine  = "native"
    runtime = "xcl"
}

// Valid — pulumi engine with python runtime
workspace {
    engine  = "pulumi"
    runtime = "python"
}

// Error — xcl runtime requires native engine
workspace {
    engine  = "pulumi"
    runtime = "xcl"    // ✗ runtime "xcl" requires engine "native"
}
```

## match {} sub-block

The `match {}` sub-block turns a universal workspace into a label-scoped workspace. A label-scoped workspace only applies to stacks whose resolved labels (from their `meta {}` block and the matched `context {}`) contain all the key-value pairs declared in `match {}`.

```xcl theme={"theme":"css-variables"}
workspace {
    name = "platform-prod"
    match {
        env = "prod"
    }
    backend s3 {
        bucket = "prod-state"
        key    = "platform/prod"
    }
}
```

If a stack's effective labels include `env = "prod"`, this workspace block applies on top of any universal workspace. Fields from the scoped workspace override the universal workspace for that stack.

A workspace block with no `match {}` is universal — it applies to every stack and is processed first in the resolution chain.

## backend {} sub-block

Declares the Pulumi state backend. See [backend](/v1/xcl/language/backend) for the full reference.

```xcl theme={"theme":"css-variables"}
workspace {
    backend s3 {
        bucket = "my-state-bucket"
        key    = "platform/prod"
        encryption {
            provider = "awskms"
            key      = "alias/pulumi-secrets"
        }
    }
}
```

## provider {} sub-block

Declares provider defaults applied to all stacks that inherit this workspace.

```xcl theme={"theme":"css-variables"}
workspace {
    provider aws {
        region  = "us-east-1"
        version = ">= 6.0.0"
    }
}
```

## tags {} sub-block

Key-value pairs applied as resource tags for all stacks that inherit this workspace. Tags **merge additively** across the resolution chain — a tag set at the workspace level is not removed by a more specific block; it is extended.

```xcl theme={"theme":"css-variables"}
workspace {
    tags {
        project     = "platform"
        managed_by  = "ubx"
    }
}
```

## hooks {} sub-block

Shell commands to run before or after a `ubx ship` or `ubx plan` operation.

```xcl theme={"theme":"css-variables"}
workspace {
    hooks {
        before_ship = ["echo 'Starting deploy'", "./scripts/pre-deploy.sh"]
        after_ship  = ["./scripts/notify-slack.sh"]
        before_plan = ["./scripts/validate-config.sh"]
        after_plan  = []
    }
}
```

| Field         | Timing                    | On failure                           |
| ------------- | ------------------------- | ------------------------------------ |
| `before_ship` | Before the deploy starts  | Abort the deploy (fail-fast)         |
| `after_ship`  | After a successful deploy | Log error, do not fail the operation |
| `before_plan` | Before the plan starts    | Abort the plan (fail-fast)           |
| `after_plan`  | After a successful plan   | Log error, do not fail the operation |

Each element is a shell command string. Commands run via `sh -c "<command>"` in the stack directory. On a non-zero exit code, `before_*` hooks immediately abort the operation; `after_*` hooks log the error and continue.

Hooks **merge additively** across the resolution chain — hooks from workspace, context, and meta are concatenated into a single list in resolution order.

## plugins {} sub-block

Declares plugins to load for stacks that inherit this workspace.

```xcl theme={"theme":"css-variables"}
workspace {
    plugins {
        my_scanner { source = "strata://scanners/my-scanner" }
        cost_est   { source = "github://ubiquex/cost-estimator" }
        local_lint { source = "file://./tools/linter" }
    }
}
```

Each plugin entry has:

* A name (bare identifier — use underscores, not hyphens: `my_scanner` not `my-scanner`)
* A `source` field specifying where to fetch the plugin

### Plugin source schemes

| Scheme      | Example                           | Description            |
| ----------- | --------------------------------- | ---------------------- |
| `strata://` | `strata://scanners/my-scanner`    | Strata plugin registry |
| `github://` | `github://ubiquex/cost-estimator` | GitHub repository      |
| `file://`   | `file://./tools/linter`           | Local filesystem path  |

Sources with an unrecognized scheme produce a **warning** (not an error). The stack still compiles.

## ai {} sub-block

```xcl theme={"theme":"css-variables"}
workspace {
    ai {
        enabled = true
        model   = "claude-haiku-4-5"

        features {
            plan_summary  = true
            cost_estimate = true
        }
    }
}
```

## scan {} sub-block

```xcl theme={"theme":"css-variables"}
workspace {
    scan {
        enabled  = true
        severity = "high"
    }
}
```

## telemetry {} sub-block

```xcl theme={"theme":"css-variables"}
workspace {
    telemetry {
        enabled = true
    }
}
```

## history {} sub-block

```xcl theme={"theme":"css-variables"}
workspace {
    history {
        enabled = true
    }
}
```

## Multiple workspace blocks

Multiple `workspace` blocks are allowed in the same compilation unit. They are merged per-field during resolution — a label-scoped workspace does not replace the universal workspace; it overrides only the fields it declares.

```xcl theme={"theme":"css-variables"}
// Universal — all stacks get this backend and these tags
workspace {
    name   = "platform"
    engine = "native"
    backend s3 {
        bucket = "state-default"
        key    = "platform"
    }
    tags {
        project = "platform"
    }
}

// Prod-scoped — stacks with env=prod get a different backend
workspace {
    name = "platform-prod"
    match {
        env = "prod"
    }
    backend s3 {
        bucket = "state-prod"
        key    = "platform/prod"
    }
}
```

A stack whose labels include `env = "prod"` sees the prod-scoped backend. A stack without that label sees the default backend. Both stacks see `tags.project = "platform"` from the universal block.

## Where workspace blocks live

`workspace {}` blocks can appear in any `.xcl` file. There is no required filename — discoverable in `workspace.xcl`, `config.xcl`, or any other file in the stack directory.

## Resolution chain

The full resolution order is:

1. Universal `workspace {}` (no `match {}`) — lowest priority
2. Label-matched `workspace {}` — fields override step 1
3. `context {}` named by the stack's `meta { context = "..." }` — fields override step 2
4. `meta {}` inside `stack {}` — highest priority

Tags and hooks from all levels are merged additively. All other fields: most specific wins.

See [meta](/v1/xcl/language/meta) for the full resolution reference.

## Error conditions

### Invalid engine value

```
engine "lambda" is not valid — valid values: native, pulumi, terraform
```

### Invalid runtime value

```
runtime "ruby" is not valid — valid values: xcl, python, typescript, go
```

### Incompatible engine / runtime

```
runtime "xcl" requires engine "native" — engine "pulumi" is not compatible
```

```
runtime "python" requires engine "pulumi" — engine "native" is not compatible
```

### Unrecognized plugin source scheme (warning)

```
warning: plugin "my-plugin" source "npm://my-plugin" has an unrecognized scheme — expected strata://, github://, or file://
```

### Duplicate backend block

```
duplicate backend block — only one backend {} is allowed inside workspace {}
```
