# Custom WASM Builds
Source: https://docs.chain.link/cre/guides/operations/custom-build
Last Updated: 2026-10-30

> For the complete documentation index, see [llms.txt](/llms.txt).

By default, `cre workflow deploy` and `cre workflow simulate` compile your Go or TypeScript source to a WASM binary automatically — no build configuration required. This works for most workflows.

`cre workflow custom-build` is an opt-in feature for advanced users who need to own the build step. Once converted, the CLI delegates compilation to a `Makefile` in your workflow directory instead of compiling your source itself.

## When to use custom WASM builds

> **NOTE: Most users don't need this**
>
> Automatic builds are the default and work for the vast majority of workflows. Use custom builds only when you have a specific reason to take control of the compilation step.

Generally, you should consider using custom WASM builds only when you have a specific reason to take control of the compilation step. Custom workflows are particularly useful for teams that need to use a custom compiler version or toolchain that differs from the CRE default compiler.

Common reasons to use custom WASM builds:

- **Custom compiler flags or build tags**: Add optimization flags, conditional compilation tags, or other build-time settings not exposed by the CLI's built-in compiler
- **CI/CD pipelines**: Build the WASM artifact once in your pipeline and promote it across environments without recompiling
- **Pre-build validation**: Add linting, type checking, formatting, or security scanning steps before compilation
- **Non-standard toolchains**: Use a custom compiler version or toolchain that differs from the CLI default
- **Language and SDK extensions**: Integrate code from other languages or custom SDKs into your build pipeline

## Convert a workflow to custom build

Run the following command from your project root:

```bash
cre workflow custom-build ./my-workflow
```

You will be prompted to confirm before any changes are made. To skip the prompt, use `--force`.

> **NOTE: What this command changes**
>
> This modifies your `workflow.yaml`, updating `workflow-path` to `./wasm/workflow.wasm` for all targets (e.g. `staging-settings`, `production-settings`). After conversion, the CLI no longer compiles your source automatically. Your `Makefile` is responsible for producing the binary.
>
> There is no automated way to reverse this with the CLI, but you can do it manually:
>
> 1. Edit `my-workflow/workflow.yaml`: change `workflow-path` back from `"./wasm/workflow.wasm"` to `"."` in each target
> 2. Delete `my-workflow/Makefile` and the `my-workflow/wasm/` directory

The following changes are made to your workflow:

- Updates `workflow-path` to `./wasm/workflow.wasm` in your `workflow.yaml` for all targets
- Creates a `Makefile` in your workflow directory with a `build` target
- Creates a `wasm/` output directory

## Build and simulate

After conversion, install dependencies (TypeScript only), then build and simulate:

```bash
# TypeScript only
bun install

make build
cre workflow simulate ./my-workflow --target staging-settings
```

The CLI picks up the compiled binary at `wasm/workflow.wasm` automatically.

## Try it yourself

Walk through the full custom build flow end to end using a hello-world project.

**1. Convert your workflow to a custom build:** Run the following command from your project root:

```bash
cre workflow custom-build ./my-workflow
```

**2. Open the generated `Makefile`:** In the `my-workflow` directory, you'll see a new `Makefile` with a `build` target.

Code snippet for my-workflow/Makefile:

```bash
.PHONY: build

build:
	bun cre-compile main.ts wasm/workflow.wasm
```

Install dependencies and run the initial build:

```bash
# TypeScript only
bun install

make build
cre workflow simulate ./my-workflow --target staging-settings
```

For a hello-world workflow you'll see output like `"Hello world!"`.

**3. Add a custom step to your `Makefile`** (highlighted line shows what to add):

Code snippet for my-workflow/Makefile:

```bash
.PHONY: build

build:
	echo "Running my custom build step..." # highlight-line
	bun cre-compile main.ts wasm/workflow.wasm
```

**4. Rebuild and simulate again:** Run the following commands from your project root:

```bash
make build
cre workflow simulate ./my-workflow --target staging-settings
```

When `make build` runs you'll see `Running my custom build step...` printed before compilation.

Swap the `echo` for any real step: type checking, linting, code generation, or a custom compiler invocation.

## Build once without converting your workflow

If you only need to compile once and reuse the binary, for example to run many simulations against the same build, you don't have to convert your workflow. Build the binary with `cre workflow build`, then pass it with `--wasm`:

```bash
cre workflow build ./my-workflow
cre workflow simulate ./my-workflow --wasm ./binary.wasm --target staging-settings
```

This leaves your `workflow.yaml` unchanged, so you can still let the CLI compile your source at any time. The `--wasm` flag is available on [`cre workflow simulate`](/cre/reference/cli/workflow#cre-workflow-simulate), [`cre workflow hash`](/cre/reference/cli/workflow#cre-workflow-hash), and [`cre workflow deploy`](/cre/reference/cli/workflow#cre-workflow-deploy). For details on how `simulate` resolves the path, see [Simulating with a pre-built binary](/cre/guides/operations/simulating-workflows#simulating-with-a-pre-built-binary).

Choose `custom-build` when you need to change how the binary is compiled. Choose `build` with `--wasm` when you only need to compile once.

## Generated Makefile

The generated `Makefile` is ready to use. The only requirement is that `make build` produces `wasm/workflow.wasm`.

**Go:**

```makefile
.PHONY: build

build:
	GOOS=wasip1 GOARCH=wasm CGO_ENABLED=0 go build -o wasm/workflow.wasm -trimpath -ldflags="-buildid= -w -s" .
```

**TypeScript:**

```makefile
.PHONY: build

build:
	bun cre-compile main.ts wasm/workflow.wasm
```

## Customizing the Makefile

Edit the generated `Makefile` to add any steps your build requires.

**Example: Go with build tags:**

```makefile
.PHONY: build

build:
	GOOS=wasip1 GOARCH=wasm CGO_ENABLED=0 go build -tags mytag -o wasm/workflow.wasm -trimpath -ldflags="-buildid= -w -s" .
```

**Example: TypeScript with type checking, linting, and formatting:**

```makefile
.PHONY: build format lint typecheck

format:
	bun run format
lint: format
	bun run lint
typecheck: lint
	bun run typecheck

build: typecheck
	bun cre-compile main.ts wasm/workflow.wasm
```

## Learn more

- [`cre workflow custom-build` reference](/cre/reference/cli/workflow#cre-workflow-custom-build): Command flags and usage
- [Simulating Workflows](/cre/guides/operations/simulating-workflows): Testing your workflow locally
- [Deploying Workflows](/cre/guides/operations/deploying-workflows): Deploying to the Workflow Registry