Select spec version:

Generate Bindings from Local Specs Beta

Generate type-safe client bindings directly from Tracking Plan YAML on disk, without a workspace, apply, or authentication.
Available Plans
  • free
  • growth
  • enterprise

Local generation is generally available from Rudder CLI v0.25.0. On v0.24.0 and earlier it is experimental and gated behind feature flags — see Enable the feature flags.

By default, rudder-cli typer generate fetches a Tracking Plan from your RudderStack workspace, which requires an access token, a Tracking Plan ID, and a network round-trip.

The --local flag reads your Tracking Plan and Data Catalog directly from the YAML files on disk instead. No workspace, no rudder-cli apply, no authentication, and no network call. Nothing is published to RudderStack when you generate.

When to use local generation

Use --local when:

  • You are iterating on an event’s shape. Changing a property and regenerating takes a second and modifies nothing shared, so you can settle the contract before anything is applied to a workspace.
  • Your specs live in Git. The Tracking Plan in your repository is the source of truth, and the generated client is a build artifact of it.
  • You are generating in CI. No credentials are required, which means no token needs to exist in the job.
  • Contributors do not have workspace access. An engineer adding a call site needs the types, not a workspace.

Use the default (remote) flow when the Tracking Plan you are generating from only exists in a workspace, or when you did not author it and do not have its specs.

Prerequisites

  • Install Rudder CLI v0.22.0 or later. Verify with rudder-cli --version.
  • Set up a local Tracking Plan project that contains your Data Catalog and Tracking Plan YAML.

No access token is required.

1. Enable the feature flags (v0.24.0 and earlier)

No setup needed from Rudder CLI v0.25.0. Local generation is generally available — --local works out of the box. The feature flags below apply only to v0.24.0 and earlier; setting them on a later version is harmless.

On Rudder CLI v0.24.0 and earlier, local generation sits behind two flags, and both must be enabled. Each can be set as an environment variable or persisted in your ~/.rudder/config.json file:

GateEnvironment variable~/.rudder/config.json
Umbrella experimental switchRUDDERSTACK_CLI_EXPERIMENTAL=true"experimental": true
The localTyper feature flagRUDDERSTACK_X_LOCAL_TYPER=true"flags": { "localTyper": true }

To enable both for a single command:

bash
RUDDERSTACK_CLI_EXPERIMENTAL=true RUDDERSTACK_X_LOCAL_TYPER=true \
  rudder-cli typer generate --local --platform typescript

The umbrella flag disables every experimental feature when it is off. Setting only RUDDERSTACK_X_LOCAL_TYPER=true on a fresh installation has no effect.

Conversely, if you already have "experimental": true in your ~/.rudder/config.json file, the RUDDERSTACK_X_LOCAL_TYPER environment variable alone is enough. This is why the same command can succeed on one machine and fail on another — always check both gates.

If either gate is off, the CLI returns:

Error: --local is experimental; enable it by setting both RUDDERSTACK_CLI_EXPERIMENTAL=true
(the umbrella experimental flag) and RUDDERSTACK_X_LOCAL_TYPER=true (the 'localTyper' flag).
The per-flag setting is ignored unless the umbrella flag is also set

2. Generate the bindings

Point --location at your project directory and --tracking-plan-id at the Tracking Plan’s spec.id:

bash
RUDDERSTACK_CLI_EXPERIMENTAL=true RUDDERSTACK_X_LOCAL_TYPER=true \
  rudder-cli typer generate \
    --local \
    --location ./my-tracking-plan-project \
    --tracking-plan-id storefront \
    --platform typescript \
    --output ./src/analytics/generated \
    --option outputFileName=index.ts
With --local, --tracking-plan-id refers to the spec.id in your local Tracking Plan YAML — not the workspace Tracking Plan ID. If the project contains exactly one Tracking Plan, you can omit the flag. If it contains more than one, the CLI lists the available IDs.

Every other flag — --platform, --output, and --option — behaves exactly as it does in the remote flow, and the generated output is identical for the same Tracking Plan.

See RudderTyper v2 Command Reference for the complete flag and option list.

Projects containing other resource types

Code generation reads only your Data Catalog and Tracking Plans. A project directory often holds specs for other resource types alongside them:

my-project/
├── data-catalog/
│   ├── events/
│   ├── properties/
│   └── custom-types/
├── tracking-plans/
│   └── storefront.yaml
├── data-graphs/            # not read by code generation
└── transformations/        # not read by code generation

typer generate --local skips resource kinds that code generation does not own, so data-graphs/ and transformations/ specs sitting beside your catalog do not interfere. This matters because a Tracking Plan must be loaded together with the Data Catalog it references. In most repositories the two only coexist at the project root, which is exactly where the other resource kinds live.

rudder-cli apply is unaffected and continues to load and validate every kind.

Skipping unknown kinds was added in Rudder CLI v0.21.0. On earlier versions, a data-graph or transformation spec in the project causes a 'kind' must be one of [...] syntax validation error and aborts the load.

Wrap the command in a script

The raw command is long, and there are a few details that are easy to get wrong. Wrap it in a script your team runs as npm run tp:sync (or the equivalent) rather than asking everyone to remember the flags:

bash
#!/usr/bin/env bash
set -euo pipefail

CATALOG_PATH="${CATALOG_PATH:-../my-tracking-plan-project}"
OUT_DIR="src/analytics/generated"

# The generated client changed shape in v0.22.0. Fail loudly rather than write
# out a client your application code no longer matches.
cli_version="$(rudder-cli --version | awk '{print $NF}')"
if [ "$(printf '0.22.0\n%s\n' "$cli_version" | sort -V | head -n1)" != "0.22.0" ]; then
  echo "error: rudder-cli $cli_version is too old; >= 0.22.0 required." >&2
  exit 1
fi

mkdir -p node_modules/.cache
TMPDIR="$PWD/node_modules/.cache" \
RUDDERSTACK_CLI_EXPERIMENTAL=true \
RUDDERSTACK_X_LOCAL_TYPER=true \
  rudder-cli typer generate \
    --local \
    --location "$CATALOG_PATH" \
    --tracking-plan-id storefront \
    --platform typescript \
    --output "$OUT_DIR" \
    --option outputFileName=index.ts

The TMPDIR line is worth keeping. On Rudder CLI versions before v0.22.0, generation writes to a temporary file in the system temporary directory and renames it onto the target. That rename fails with a cross-device link error when your repository is on a different volume. Keeping the temporary file next to the destination avoids this.

Record which specs produced the client

Types come from files on disk, so a stale or wrong-branch checkout silently produces a different, valid-looking client. It compiles, it passes your tests, and it emits the wrong shape. Nothing in the type system notices.

Record the provenance next to the generated client and regenerate it on every sync:

bash
cat > "$OUT_DIR/SOURCE.md" <<EOF
<!-- Written by tp:sync. Do not edit by hand. -->

| | |
| --- | --- |
| catalog commit | \`$(git -C "$CATALOG_PATH" rev-parse HEAD)\` |
| branch at generation | \`$(git -C "$CATALOG_PATH" rev-parse --abbrev-ref HEAD)\` |
| rudder-cli | \`$cli_version\` |
EOF

Check this file before committing a regenerated client, and when reviewing a pull request that changes one.

For the full workflow — including how to keep a Tracking Plan repository and an application repository in step, and how to enforce it in CI — see Instrumentation Workflow.

Troubleshooting

ErrorCause and fix
--local is experimental; enable it by setting both ...You are on Rudder CLI v0.24.0 or earlier. Upgrade to v0.25.0 or later, or enable both feature flags.
no tracking plans found in the project--location does not point at a directory containing a tracking-plans/ spec.
multiple tracking plans found, specify --tracking-plan-idPass the spec.id of the plan you want. The error lists the available IDs.
tracking plan "<id>" not found in local specsThe --tracking-plan-id value does not match any spec.id in the project.
'kind' must be one of [...]The project contains a resource kind code generation does not own, on Rudder CLI earlier than v0.21.0. Upgrade the CLI.
cross-device linkThe repository is on a different volume than the system temporary directory, on Rudder CLI earlier than v0.22.0. Set TMPDIR to a directory inside the repository, or upgrade.

Questions? Let's figure it out together.

Join the RudderStack Slack community to connect with other users, customers, and the RudderStack team — or reach out for direct support.