> Part of the walkerOS documentation. Project overview and full index: <https://www.walkeros.io/llms.txt>

# Reference Syntax

walkerOS flow configs (flow\.json) support dynamic references inside string values. They let you pull in variables, environment values, contract fragments, store instances, secrets, and inline JavaScript without duplicating configuration.

Snippets on this page show only the keys a reference needs; a complete flow\.json also has `"version": 4` and its steps.

## The one rule[​](#the-one-rule "Direct link to The one rule")

walkerOS uses **two separator characters**, each with a clear meaning:

| Separator | Meaning                                                                                         |
| --------- | ----------------------------------------------------------------------------------------------- |
| **`.`**   | A key or path. The resolver looks up what follows in a map or walks it as a dotted path.        |
| **`:`**   | A literal value or raw-code payload. The resolver uses what follows verbatim, it is not a name. |

Every reference follows that rule. There are no exceptions.

## All references[​](#all-references "Direct link to All references")

```
$var.name              look up variables[name] (whole-string returns native type)

$var.name.deep.path    walk a dotted path inside the variable

$env.NAME              read process.env[NAME]

$env.NAME:default      read process.env[NAME] with a literal fallback

$contract.name         inject a whole named contract entry

$contract.name.events  walk the contract path

$store.id              inject a store instance (resolved at bundle time)

$secret.NAME           inject a secret value (resolved at deploy time)

$code:(event) => ...   inline JavaScript (resolved at bundle time)
```

## `$var.`: variables[​](#var--variables "Direct link to var--variables")

Look up a value in the `variables` map at config, flow, or step level. Step overrides flow overrides config.

Variables hold any JSON value, scalars (string, number, boolean), objects, arrays, or whole mapping templates. The reference may include a deep path that walks the value.

```
{

  "variables": {

    "measurementId": "G-XXXXXX",

    "ga4Items": {

      "loop": ["nested", { "map": { "item_id": "data.id" } }]

    },

    "api": { "version": "v2", "url": "https://api.example.com" }

  },

  "flows": {

    "web": {

      "config": { "platform": "web" },

      "destinations": {

        "gtag": {

          "package": "@walkeros/web-destination-gtag",

          "config": {

            "settings": {

              "ga4": { "measurementId": "$var.measurementId" }

            },

            "mapping": {

              "order": {

                "complete": {

                  "data": { "map": { "items": "$var.ga4Items" } }

                }

              }

            }

          }

        },

        "api": {

          "package": "@walkeros/web-destination-api",

          "config": {

            "settings": {

              "url": "$var.api.url",

              "headers": { "X-Api-Version": "$var.api.version" }

            }

          }

        }

      }

    }

  }

}
```

**Resolution rules:**

* A whole-string reference (`"$var.api.url"`) replaces the value with the variable's native type. Object, array, number, and boolean values are preserved.
* An inline reference (`"Bearer $var.token"`) substitutes a scalar mid-string. Object or array values throw, scalars only.
* Variables may reference other variables. Resolution is recursive with cycle detection.

In [`flow-complete.json`](https://github.com/elbwalker/walkerOS/blob/main/packages/cli/examples/flow-complete.json), the tested example flow, variables live at all three levels:

`/variables`

```json
{
  "currency": "EUR",
  "gcp": {
    "project": "$env.GCP_PROJECT:demo-project",
    "dataset": "$env.BQ_DATASET:walkeros",
    "topic": "$env.PUBSUB_TOPIC:walkeros-events"
  }
}
```

Root variables are shared by all flows; a flow or a step can override them. [Guide chapter `references`](https://github.com/elbwalker/walkerOS/blob/main/packages/cli/examples/flow-complete.md#references-values-from-outside-the-file)

`/flows/server/variables`

```json
{
  "logLevel": "$env.LOG_LEVEL:INFO"
}
```

Flow variables win over root variables for one flow. [Guide chapter `references`](https://github.com/elbwalker/walkerOS/blob/main/packages/cli/examples/flow-complete.md#references-values-from-outside-the-file)

`/flows/server/destinations/piwikpro/variables`

```json
{
  "siteId": "$env.PIWIK_SITE_ID:e8f3a1c2-0b4d-4e5f-9a6b-7c8d9e0f1a2b"
}
```

Step variables win over flow and root variables for one step. [Guide chapter `references`](https://github.com/elbwalker/walkerOS/blob/main/packages/cli/examples/flow-complete.md#references-values-from-outside-the-file)

A whole-string reference, a deep path and an inline reference:

`/flows/web/destinations/ga4/config/policy/data.currency/1/value`: `"$var.currency"`. A whole-string $var keeps the variable type. [Guide chapter `references`](https://github.com/elbwalker/walkerOS/blob/main/packages/cli/examples/flow-complete.md#references-values-from-outside-the-file)

`/flows/server/destinations/pubsub/config/settings/projectId`: `"$var.gcp.project"`. $var.gcp.project reads a path inside a variable. [Guide chapter `references`](https://github.com/elbwalker/walkerOS/blob/main/packages/cli/examples/flow-complete.md#references-values-from-outside-the-file)

`/flows/warehouse/sources/pubsub/config/setup/deadLetterPolicy/deadLetterTopic`: `"projects/$var.gcp.project/topics/walkeros-dead-letter"`. Inside a longer string $var is replaced in place, here in a full topic name. [Guide chapter `references`](https://github.com/elbwalker/walkerOS/blob/main/packages/cli/examples/flow-complete.md#references-values-from-outside-the-file)

**Naming convention:** when variables hold structures (mapping templates, matchers, consent objects), pick a name that signals the shape, for example `ga4ItemMapping`, `ga4ItemsLoop`, `consentMarketing`, `getMastertagJs`. Keep the convention consistent within a single config; we don't enforce a global prefix or suffix rule.

## `$env.`: environment variables[​](#env--environment-variables "Direct link to env--environment-variables")

Read from `process.env` at runtime. Optionally provide a literal fallback with the `:default` suffix.

```
{

  "variables": {

    "apiUrl": "$env.API_URL:http://localhost:8080/collect",

    "pixelId": "$env.META_PIXEL_ID"

  }

}
```

The `:` here is the **default-value separator**, not a name delimiter. The token after `:` is used verbatim.

Use `$env.` for non-secret config (IDs, hostnames, regions). For credentials, tokens, and private keys managed by the secret manager, use `$secret.`: the deploy pipeline only injects values referenced as `$secret.NAME`.

`/variables/gcp/project`: `"$env.GCP_PROJECT:demo-project"`. $env.NAME:default works out of the box and takes the environment value when set. [Guide chapter `references`](https://github.com/elbwalker/walkerOS/blob/main/packages/cli/examples/flow-complete.md#references-values-from-outside-the-file)

`/flows/server/transformers/fingerprint/config/settings/salt`: `"$env.FINGERPRINT_SALT"`. $env without a default must be set: a secret salt never gets a public default. [Guide chapter `references`](https://github.com/elbwalker/walkerOS/blob/main/packages/cli/examples/flow-complete.md#references-values-from-outside-the-file)

Web flows resolve `$env` at build time, from the set the flow declares under `config.bundle.env`:

`/flows/web/config/bundle/env`

```json
{
  "ENVIRONMENT": "production"
}
```

Web $env is resolved at build time from this declared set, so every build is the same. [Guide chapter `references`](https://github.com/elbwalker/walkerOS/blob/main/packages/cli/examples/flow-complete.md#references-values-from-outside-the-file)

## `$contract.`: contract references[​](#contract--contract-references "Direct link to contract--contract-references")

Inject a fragment of a named contract entry. Same whole-string and deep-path rules as `$var.`. The contract is fully resolved (extend + wildcards) before path access, so the value you get is the merged shape.

See [Contract](/preview/pr-749/docs/getting-started/flow/contract.md) for the full structure.

`/flows/server/transformers/validate/config/settings/contract/0`: `"$contract.server"`. $contract.server hands the resolved contract to the validate step. [Guide chapter `references`](https://github.com/elbwalker/walkerOS/blob/main/packages/cli/examples/flow-complete.md#references-values-from-outside-the-file)

```
{

  "contract": {

    "default": {

      "schema": {

        "properties": {

          "globals": { "required": ["country"] }

        }

      },

      "events": {

        "product": {

          "add": { "properties": { "data": { "required": ["id", "name"] } } }

        }

      }

    }

  },

  "flows": {

    "web": {

      "config": { "platform": "web" },

      "transformers": {

        "validate": {

          "package": "@walkeros/transformer-validate",

          "config": {

            "settings": {

              "contract": ["$contract.default"],

              "mode": "strict"

            }

          }

        }

      }

    }

  }

}
```

A deep path such as `$contract.default.schema` injects only that part of the resolved entry, here the full-event JSON Schema, which the validate transformer also accepts as a `contract` entry.

## `$store.`: store wiring[​](#store--store-wiring "Direct link to store--store-wiring")

Inject a store instance declared under `stores`. Wired through a component's `env` so the bundler can resolve to the real store at build time.

```
{

  "flows": {

    "server": {

      "config": { "platform": "server" },

      "stores": {

        "assets": {

          "package": "@walkeros/server-store-fs",

          "config": { "settings": { "basePath": "./public" }, "file": true }

        }

      },

      "transformers": {

        "file": {

          "package": "@walkeros/server-transformer-file",

          "config": { "settings": { "prefix": "/static" } },

          "env": { "store": "$store.assets" }

        }

      }

    }

  }

}
```

Store IDs are plain identifiers (camelCase). The `.` is the separator, not a path walker, store IDs do not contain dots.

`/flows/server/transformers/file/env/store`: `"$store.assets"`. $store.assets injects a store into a step. [Guide chapter `references`](https://github.com/elbwalker/walkerOS/blob/main/packages/cli/examples/flow-complete.md#references-values-from-outside-the-file)

## `$secret.`: secrets[​](#secret--secrets "Direct link to secret--secrets")

Inject a secret resolved at deploy time. Secrets are stored outside the config and never written into customer databases alongside the flow.

```
{

  "flows": {

    "server": {

      "config": { "platform": "server" },

      "destinations": {

        "api": {

          "package": "@walkeros/server-destination-api",

          "config": {

            "settings": {

              "url": "https://api.example.com/events",

              "headers": { "Authorization": "$secret.API_AUTHORIZATION" }

            }

          }

        }

      }

    }

  }

}
```

Secret names are uppercase: `[A-Z0-9_]+`. The `.` is the separator, secrets have no internal structure.

A `$secret.` reference must be the entire string value. Inside a longer string it is not resolved and stays literal text. When a header needs a prefix, store the complete value in the secret, for example `Bearer abc123` for `API_AUTHORIZATION` above.

`/flows/server/destinations/pubsub/config/credentials`: `"$secret.GCP_SA"`. $secret is read at start and never baked into an artifact; web flows reject it. [Guide chapter `references`](https://github.com/elbwalker/walkerOS/blob/main/packages/cli/examples/flow-complete.md#references-values-from-outside-the-file)

Use `$secret.` for credentials, tokens, and private keys (for example a service account JSON on `config.credentials`). The app's deploy pipeline detects `$secret.NAME` references and injects the managed secret value into the server runner's environment at runtime. A managed secret referenced as `$env.NAME` is **not** injected, so reach for `$secret.` whenever the value comes from the secret manager. Secrets resolve on server flows only.

## `$code:`: inline code[​](#code--inline-code "Direct link to code--inline-code")

Embed a JavaScript function as a string. The bundler compiles the payload into real JS at build time. Everything after `$code:` is the raw function body.

```
{

  "variables": {

    "onlyProducts": {

      "condition": "$code:(entity) => entity.entity === 'product'"

    }

  }

}
```

The `:` here marks the **payload**. Nothing after the colon is looked up, it is compiled as-is.

`/flows/web/destinations/collect/config/settings/transform`: `"$code:(event) => { const { timing, ...rest } = event; return rest; }"`. $code: puts a function into JSON. [Guide chapter `references`](https://github.com/elbwalker/walkerOS/blob/main/packages/cli/examples/flow-complete.md#references-values-from-outside-the-file)

## `$flow.`: cross-flow references[​](#flow-cross-flow-references "Direct link to flow-cross-flow-references")

Read a value from another flow's `config` block in the same file. The web flow sends to the server flow's URL:

`/flows/web/destinations/collect/config/settings/url`: `"$flow.server.url"`. $flow\.server.url points the browser at the server flow; it is whole-string only. [Guide chapter `references`](https://github.com/elbwalker/walkerOS/blob/main/packages/cli/examples/flow-complete.md#references-values-from-outside-the-file)

See [Cross-flow references](/preview/pr-749/docs/getting-started/flow.md#cross-flow-references-with-flow) for the rules.

## Request values: `ingest`[​](#request-values-ingest "Direct link to request-values-ingest")

Request context is not a `$` reference. A server source lifts it into `ingest` with its `config.ingest` mapping, and later steps read it by path (`ingest.ip`, `ingest.path`), for example in a route `match` or a `state` key:

`/flows/server/sources/express/config/ingest`

```json
{
  "map": {
    "ip": "ip",
    "path": "path",
    "method": "method",
    "url": "url",
    "body": "body",
    "origin": "headers.origin",
    "userAgent": "headers.user-agent",
    "acceptLanguage": "headers.accept-language"
  }
}
```

ingest keeps the request context (ip, path, headers) for later steps without putting it on the event. [Guide chapter `server-entry`](https://github.com/elbwalker/walkerOS/blob/main/packages/cli/examples/flow-complete.md#server-entry-a-first-party-endpoint-and-a-ga4-migration-path)

## Cascade and resolution order[​](#cascade-and-resolution-order "Direct link to Cascade and resolution order")

`variables` can live at three levels. Priority (highest wins):

1. Step level (`sources.*`, `transformers.*`, `destinations.*`, `stores.*`)
2. Flow level (`flows.<name>.variables`)
3. Config root (`variables`)

Resolution runs at `getFlowSettings()` in `@walkeros/core`, the runtime replaces every reference before the bundler or collector sees the config.

## Whole-value and inline references[​](#whole-value-and-inline-references "Direct link to Whole-value and inline references")

`$flow.`, `$store.`, `$secret.` and `$contract.` resolve only when the reference is the entire string value. `$var.` and `$env.` also resolve inside a longer string. `walkeros validate` warns about a whole-value reference that would not resolve:

* **Malformed:** `"$flow.server.url/collect"` or `"$secret.api_key"` does not match the reference grammar (`$secret.` names are uppercase letters, digits and `_`), so it would not resolve.
* **Inline:** `"https://x/$store.cache"` uses `$store.` mid-string, so it would ship as literal text. Use the reference as the entire value, or compose the string with `$var` or `$env`.

`$code:` values, `$comment` values, the root `contract` block, a step's `config.settings.contract`, and the `title` and `description` of the config, a flow, a step or a step example are not checked.

## What else to read[​](#what-else-to-read "Direct link to What else to read")

* [`@walkeros/core` reference exports](https://github.com/elbwalker/walkerOS/blob/main/packages/core/src/references.ts): `REF_VAR_FULL`, `REF_VAR_INLINE`, `REF_ENV`, `REF_CONTRACT`, `REF_FLOW`, `REF_STORE`, `REF_SECRET`, `REF_CODE_PREFIX`. The single source of truth for the regex patterns. Also exports `scanFlowRefs(value)` which walks any value (string, array, object) and returns every `$flow.<name>` reference found, including refs nested inside `$code:` snippets.
* [Stores guide](/preview/pr-749/docs/stores.md): wiring stores via `$store.`.
* [Mapping guide](/preview/pr-749/docs/mapping.md): `$code:` and mapping-value shortcuts.
