Parameters and variables in .goat scripts

.goat scripts can use arguments passed at runtime, local variables, and environment variables.

Four basic mechanisms are available:

  • {{args}} — all arguments passed to the script,
  • {{args.name}} — a selected named argument,
  • {{variable}} — a local variable defined with set,
  • {{env.NAME}} — an environment variable.

Arguments and local variables belong to the current script. A child script receives them only when they are passed explicitly.


Passing arguments to a script

Script arguments are passed after the -- separator.

goat run:script --path=@goatcms/herd/translate.goat -- --force

In this example:

--path=@goatcms/herd/translate.goat

is an option of run:script, while:

--force

is an argument of the translate.goat script.

You can pass any number of arguments:

goat run:script --path=herd/example.goat -- --force --model=gpt-5 --verbose

Without the -- separator, arguments are interpreted as options of the run:script command.


All arguments — {{args}}

{{args}} expands to all arguments passed to the current script.

Example:

translate:sync --catalog="catalog.json" {{args}}

Running:

goat run:script --path=@goatcms/herd/translate.goat -- --force --model=gpt-5

is equivalent to passing:

--force --model=gpt-5

to translate:sync.

Argument order is preserved.

If no arguments were passed to the script, {{args}} expands to an empty list. This is valid and does not cause an error.

This means you can safely write:

translate:sync --catalog="catalog.json" {{args}}

and use the same script both without additional options:

goat run:script --path=@goatcms/herd/translate.goat

and with them:

goat run:script --path=@goatcms/herd/translate.goat -- --force

{{args}} as a standalone token

{{args}} can only be used as a standalone token.

Valid:

command {{args}}

Invalid:

command --options={{args}}

This is required because {{args}} may expand to zero, one, or multiple arguments.


Named arguments — {{args.name}}

You can reference a specific argument using:

{{args.name}}

For example:

command {{args.model}}

Long-form arguments are supported in the following forms:

--model
--model=gpt-5
--model gpt-5

Preserving the original form

The argument is passed in the same form in which it was originally provided.

For:

--model=gpt-5

the expression:

{{args.model}}

passes:

--model=gpt-5

For:

--model gpt-5

it passes two tokens:

--model
gpt-5

Multiple occurrences

If the same argument is provided more than once, all occurrences are preserved in their original order.

Example:

--tag=a --tag b --tag=c

The reference:

{{args.tag}}

passes all three occurrences.

Missing arguments

Referencing an argument that was not provided stops script execution with an error.

For example:

command {{args.model}}

requires the --model argument to be present.

If an argument is optional, it is usually more convenient to forward all optional arguments using:

{{args}}

Standalone token

Like {{args}}, {{args.name}} can only be used as a standalone token.

Valid:

command {{args.model}}

Invalid:

command --model={{args.model}}

Local variables — set

You can define a local variable with:

set model = "gpt-5"

You can then use it in subsequent commands:

command --model={{model}}

or as a standalone argument:

command {{model}}

Variables are available from the point at which they are declared and belong only to the current script.

Example:

set catalog = "catalog.json"
set model = "gpt-5"

translate:sync --catalog={{catalog}} --model={{model}}

Variable values are not split again

The value of a local variable is always treated as a single value.

Example:

set options = "--foo --bar"

command {{options}}

passes one argument:

--foo --bar

rather than two separate arguments:

--foo
--bar

If you need to pass multiple arguments, use {{args}} or write them directly in the command.


Environment variables — {{env.NAME}}

Environment variables can be referenced using:

{{env.NAME}}

Example:

translate:sync --model={{env.GOAT_OPENAI_MODEL}}

They can also be used inside tokens:

command --endpoint={{env.API_ENDPOINT}}

The value of an environment variable is treated as a single value and is not split into additional arguments.

If the requested environment variable does not exist, script execution stops with an error.


Using variables inside quoted values

Local and environment variables can also be used inside quoted values.

set model = "gpt-5"

translate:sync --model="{{model}}"

and:

translate:sync --model="{{env.GOAT_OPENAI_MODEL}}"

You can also combine them with static text:

set locale = "pl"

command --catalog="catalog-{{locale}}.json"

Argument and variable scope

Each .goat script has its own:

  • arguments,
  • local variables defined with set.

They are not automatically available in child scripts.

Example:

run:script --path=herd/child.goat

child.goat starts without the parent script's arguments or local variables.

Environment variables remain available through:

{{env.NAME}}

Passing arguments to a child script

If a child script should receive the arguments of its parent script, they must be passed explicitly.

run:script --path=herd/child.goat -- {{args}}

In this case, child.goat receives all arguments of the current script.

You can also pass only a selected named argument:

run:script --path=herd/child.goat -- {{args.model}}

or build an argument from a local variable:

set model = "gpt-5"

run:script --path=herd/child.goat -- --model={{model}}

This keeps script boundaries explicit: each script receives only the values that are intentionally passed to it.


Available interpolation forms

SyntaxMeaningCan expand to multiple argumentsCan be part of a token
{{args}}all script argumentsyesno
{{args.name}}selected named argumentyesno
{{variable}}local variablenoyes
{{env.NAME}}environment variablenoyes

Valid examples:

command {{args}}
command {{args.model}}
command {{model}}
command --model={{model}}
command --model={{env.GOAT_OPENAI_MODEL}}

Invalid examples:

command prefix-{{args}}
command --model={{args.model}}

Example: forwarding options to translate:sync

A script can forward all received arguments directly to translate:sync:

translate:sync --catalog="catalog.json" {{args}}

A regular invocation:

goat run:script --path=@goatcms/herd/translate.goat

does not pass any additional options.

Running:

goat run:script --path=@goatcms/herd/translate.goat -- --force

passes --force to translate:sync.

Similarly:

goat run:script --path=@goatcms/herd/translate.goat -- --force --model=gpt-5

passes both options in the same order.


Complete script example

set catalog = "catalog.json"
set defaultModel = "gpt-5"

translate:prepare --catalog={{catalog}}
translate:sync --catalog={{catalog}} --fallback-model={{defaultModel}} {{args}}

The script can be run without additional arguments:

goat run:script --path=herd/example.goat

or with extra options:

goat run:script --path=herd/example.goat -- --force --model=gpt-5

Errors

Script execution stops when, among other cases:

  • an undefined local variable is used,
  • the requested environment variable does not exist,
  • {{args.name}} references an argument that was not provided,
  • {{args}} or {{args.name}} is used inside another token.

The error message points to the relevant location in the script so the invalid reference can be identified.