# AWL commands

Declared command syntax, arguments, capture, working directories and exports.

A declared command names programs and arguments. It is parsed without a shell. An action can run it and capture its outcome, text or JSON result.

## Declaration words

- `command`: In `runs command <name>`, names the command declaration a worker action runs. The declaration itself is written as a just recipe: `name params:` over indented command lines, no keyword. Arguments: form: value-word; positions: run-capture, recipe-step.
- `set`: Opens the document's `set working-directory := "…"` line — just's own file-level setting — naming the directory every command declaration in the document runs in. Arguments: form: declaration; positions: top-level.
- `export`: Opens a document's `export NAME := "value"` line — just's own file-level export — an environment binding, as a literal, for every command declaration in the document. Arguments: form: declaration; positions: top-level.


A command declaration begins with a bare name and parameters followed by a colon. An action uses the command keyword to reference that declaration.

## Complete syntax examples

**Command declarations — syntax 1**

```text
tag_release tag_name commit:
  git tag -- {{tag_name}} {{commit}}
```


**Command declarations — syntax 2**

```text
set working-directory := "{workspace_root}"
export GIT_PAGER := "cat"
```


**Command declarations — syntax 3**

```text
diff_census base_pin cargo_bin="cargo":
  git diff --no-ext-diff --name-only {{base_pin}}..HEAD
```


## Argument rules

Arguments are split once when the document is checked. A substituted parameter stays one argument, including spaces. Shell pipelines, redirections, substitutions and control operators are refused when written as shell syntax. To use a shell deliberately, name it as the program.

Blank lines and hash comments are skipped. A trailing backslash joins the next line. An at-sign prefix is stripped. Ignore-error prefixes and a first-line shebang are refused. Every declared command must contain an executable line.

A child process receives the declared environment. Working-directory and export declarations are explicit. A typed directory parameter can select a command's working directory.

## Capture and failure

A capture form chooses the command outcome, trimmed stdout text or decoded stdout JSON. The declared action result still controls validation. Nonzero exit, malformed output and unavailable programs are named failures.

> The host is the trust boundary
> There is no sandbox. A declared body can run a program with the permissions of its executor. Review the document and the programs before deploying or firing it.


## Command contract details

- `name param param="default":`: A bare command header. Parameters are untyped command words. Single-quoted raw defaults are accepted and formatted to double quotes. Defaults are literal; interpolation in one is refused.
- `{{param}}`: A declared parameter interpolated into one argument, including inside quotes. Values never re-enter the parser. {{{{ writes a literal opening pair. Expressions and undeclared fills are refused.
- `Program position`: The first argument must be a nonempty literal program. A parameter cannot supply all or any part of it.
- `Leading dash`: A caller-filled argument beginning with a dash is refused while still in option position. A preceding literal -- permits it. A literal option prefix written by the author is allowed.
- `Quotes and shell syntax`: Single quotes preserve literal bytes. Shell operators, globs, substitutions, home expansion and shell escape forms are refused where a shell would act on them; name a shell explicitly to execute shell code.
- `Line execution`: Each line is a separate process, in written order. A directory or variable change on one line does not affect the next. The first nonzero exit fails the command.
- `Environment and stdin`: Only PATH plus document exports are present. An exported PATH replaces the executor value. Standard input is closed.
- `Captured result`: The concatenated stdout has one trailing newline removed, including a preceding carriage return. Stderr goes to the live transcript and failure detail. Capture binds stdout.
- `runs command NAME`: Text capture returning String; runs text is accepted and formatted to the bare form.
- `runs json command NAME`: Decode stdout into the declared return type. Missing required command parameters or values without a single-word argument form are refused.
- `run body in a workflow`: Returns a record over a subset of exit_code: Int, stdout: String and stderr: String. Worker-only run text and run json selectors are refused in this family.
- `run body in a worker document`: Bare run returns the outcome record; run text returns String; run json decodes a non-Nil declared type. Malformed JSON is terminal; nonzero exit is retryable; an unspawnable program or cancellation is terminal.
