<!-- GENERATED by docs-gen from oxdock-parser metadata. Do not edit by hand. -->
## Command Reference
| Command | Syntax |
| --- | --- |
| [`WORKDIR`](#workdir) | `WORKDIR <path>` |
| [`WORKSPACE`](#workspace) | `WORKSPACE SNAPSHOT\|LOCAL` |
| [`ENV`](#env) | `ENV KEY=value` |
| [`INHERIT_ENV`](#inherit_env) | `INHERIT_ENV <key>...` |
| [`ECHO`](#echo) | `ECHO <message>` |
| [`RUN`](#run) | `RUN <command...>` |
| [`COPY`](#copy) | `COPY [--from-current-workspace] <from> <to>` |
| [`COPY_GIT`](#copy_git) | `COPY_GIT [--include-dirty] <rev> <src> <dst>` |
| [`SYMLINK`](#symlink) | `SYMLINK <from> <to>` |
| [`MKDIR`](#mkdir) | `MKDIR <path>` |
| [`LS`](#ls) | `LS [<path>]` |
| [`CWD`](#cwd) | `CWD` |
| [`READ`](#read) | `READ [<path>]` |
| [`READ_LINE`](#read_line) | `READ_LINE $var` |
| [`WRITE`](#write) | `WRITE <path> [<contents>]` |
| [`APPEND`](#append) | `APPEND <path> [<contents>]` |
| [`EXPAND`](#expand) | `EXPAND [<path>] [<KEY=val> ...]` |
| [`ASSERT_FILE`](#assert_file) | `ASSERT_FILE [--hash <sha256>] <path> [<expected>]` |
| [`ASSERT_DIR`](#assert_dir) | `ASSERT_DIR <path>` |
| [`ASSERT_ABSENT`](#assert_absent) | `ASSERT_ABSENT <path>` |
| [`ASSERT_STDOUT`](#assert_stdout) | `ASSERT_STDOUT <substring>` |
| [`HASH_SHA256`](#hash_sha256) | `HASH_SHA256 <path>` |
| [`EXIT`](#exit) | `EXIT <code>` |
| [`SLEEP`](#sleep) | `SLEEP <duration>` |
| [`WITH_IO`](#with_io) | `WITH_IO [bindings] <command> \| WITH_IO [bindings] { <commands> }` |
| [`FOR`](#for) | `FOR $item IN <expr> { <commands> } \| FOR $key, $value IN <expr> { <commands> }` |
| [`IF`](#if) | `IF <expr> { <commands> } [ELSE IF <expr> { <commands> }] [ELSE { <commands> }]` |
| [`LET`](#let) | `LET $var = <expr> \| LET $var = ASYNC { <commands> }` |
| [`ASYNC`](#async) | `ASYNC <command...> \| ASYNC { <commands> } \| LET $var = ASYNC { <commands> }` |
| [`AWAIT`](#await) | `AWAIT $var` |
| [`CANCEL`](#cancel) | `CANCEL $var` |
| [`TIMEOUT`](#timeout) | `TIMEOUT <duration> <command...> \| TIMEOUT <duration> { <commands> } \| TIMEOUT <duration> AWAIT $var` |
### WITH_IO
Reroute standard streams.
**Syntax:** `WITH_IO [bindings] <command> | WITH_IO [bindings] { <commands> }`
Reroutes the standard streams of the next command or, in block form, of every enclosed command. Bindings map streams (`stdin`, `stdout`, `stderr`) to named pipes (`stdout=pipe:name`). Pipe names registered by the host runtime tee structured output elsewhere; a name bound as output can later feed another command's `stdin`, connecting commands without touching the terminal. Nested blocks stack defaults; inline bindings override inherited ones for their command only; closing a block restores previous wiring.
**Examples:**
**Example: with_io block**
```oxdock
WITH_IO [stdout=pipe:log] {
ECHO first
ECHO second
}
WITH_IO [stdin=pipe:log] WRITE captured.txt
```
### FOR
Iterate over a list or map.
**Syntax:** `FOR $item IN <expr> { <commands> } | FOR $key, $value IN <expr> { <commands> }`
The loop variable receives each element (lists) or value (maps); with two variables, the first receives the key. Loop variables are scoped to the loop body and do not leak outward. The body may be a braced block or a single-line `{ ... }` command. `GLOB("...")` patterns must be quoted (`*` is not a bare word, so `GLOB(*)` is a parse error); GLOB returns a root-relative sorted list, empty when nothing matches, and rejects `..` escapes.
**Examples:**
**Example: for loop**
```oxdock
LET $items = ["a", "b"]
FOR $item IN $items {
ECHO $item
}
LET $map = {"x": 1}
FOR $k, $v IN $map {
ECHO "$k=$v"
}
```
**Example: expand every match**
```oxdock
# single-line body; $x is a template path, WHO an override
WRITE a.txt "hi \{{ env:WHO }}!"
FOR $x IN GLOB("*.txt") { EXPAND $x WHO=World }
ASSERT_STDOUT "hi World!"
```
### IF
Conditional execution.
**Syntax:** `IF <expr> { <commands> } [ELSE IF <expr> { <commands> }] [ELSE { <commands> }]`
The condition is evaluated as a boolean expression. Prefix `!` negates (`IF !false`); only Bool values are accepted as conditions.
**Examples:**
**Example: if else**
```oxdock
IF true {
ECHO yes
} ELSE {
ECHO no
}
IF false {
ECHO skipped
} ELSE IF true {
ECHO fallback
}
IF !false {
ECHO inverted
}
```
### LET
Bind script-local variables.
**Syntax:** `LET $var = <expr> | LET $var = ASYNC { <commands> }`
Assigns a value to a script-local variable. Variables are usable in templates (`{{ $var }}`), guards, and expressions. With `ASYNC`, spawns a background task and stores its handle (see ASYNC). The `$` sigil on the name is mandatory. The right-hand side is always an expression — literals, lists, maps, comparisons, `GLOB("*.md")` — never a `{{ ... }}` template; interpolation happens in string values, not here. Bare words need no quotes: `LET $d = 30s` binds the same string as `LET $d = "30s"`.
**Examples:**
**Example: let**
```oxdock
LET $name = "world"
ECHO "hello, {{ $name }}"
LET $items = ["a", "b"]
LET $count = 42
```
**Example: glob binding**
```oxdock
# the RHS is an expression: GLOB(...) runs and binds a list
WRITE a.txt "x"
LET $files = GLOB("*.txt")
FOR $f IN $files { ECHO $f }
ASSERT_STDOUT "a.txt"
```
**Example: scoped variable reverts**
```oxdock
# LET inside a braced block reverts when the block exits
LET $a = "outer"
[bool:true] {
LET $a = "inner"
WRITE inner.txt "{{ $a }}"
}
WRITE outer.txt "{{ $a }}"
ASSERT_FILE inner.txt "inner"
ASSERT_FILE outer.txt "outer"
```
### ASYNC
Run steps in a background thread.
**Syntax:** `ASYNC <command...> | ASYNC { <commands> } | LET $var = ASYNC { <commands> }`
Runs a command or block of commands in a background thread with subshell isolation. Mutations (ENV, WORKDIR) stay within the block. With `LET`, stores a task handle for `AWAIT`.
**Examples:**
**Example: async**
```oxdock
ASYNC ECHO "first"
ASYNC {
ECHO "first"
ECHO "second"
}
```
**Example: async task handle**
```oxdock
LET $task = ASYNC {
ECHO "built"
}
AWAIT $task
```
### AWAIT
Join a background task.
**Syntax:** `AWAIT $var`
Blocks until the named task completes. Propagates errors if the task failed.
**Examples:**
**Example: await**
```oxdock
LET $task = ASYNC ECHO "done"
AWAIT $task
```
### CANCEL
Synchronously cancel a background task.
**Syntax:** `CANCEL $var`
Kills the named background task spawned via LET $var = ASYNC .... Blocking: returns only after the task thread has been joined and its OS process reaped, so no residual filesystem or stream mutation follows. A later AWAIT $var reports cancellation. Only named tasks can be cancelled.
**Examples:**
**Example: cancel**
```oxdock
LET $task = ASYNC SLEEP 30s
CANCEL $task
```
### TIMEOUT
Enforce an execution deadline.
**Syntax:** `TIMEOUT <duration> <command...> | TIMEOUT <duration> { <commands> } | TIMEOUT <duration> AWAIT $var`
Aborts the wrapped step or block with a deadline error if it exceeds the duration (e.g. 500ms, 10s, 2m; a bare number means seconds). A blocking foreground process is killed.
**Examples:**
**Example: timeout**
```oxdock
TIMEOUT 30s WRITE heartbeat.txt alive
```
**Example: timeout block**
```oxdock
TIMEOUT 30s {
WRITE a.txt one
WRITE b.txt two
}
```
**Example: timeout variable duration**
```oxdock
# durations resolve at runtime, so variables work too
LET $budget = "30s"
TIMEOUT $budget WRITE heartbeat.txt alive
ASSERT_FILE heartbeat.txt alive
```
### WORKDIR
Change the working directory.
**Syntax:** `WORKDIR <path>`
Sets the current working directory. Relative paths resolve against the current directory; `/` resets to the workspace root. Paths cannot escape the workspace.
**Arguments:**
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `path` | [`path`](#value-type-path) | yes | Directory to change to |
**Examples:**
**Example: change working directory**
```oxdock
WORKDIR project/src
WRITE generated.txt generated-under-workdir
ASSERT_FILE generated.txt generated-under-workdir
```
### WORKSPACE
Switch workspace roots.
**Syntax:** `WORKSPACE SNAPSHOT|LOCAL`
SNAPSHOT or LOCAL root.
**Arguments:**
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `target` | `SNAPSHOT\|LOCAL` | yes | Target root |
**Examples:**
**Example: switch roots**
```oxdock
WORKSPACE LOCAL
```
### ENV
Set an environment variable.
**Syntax:** `ENV KEY=value`
Inserts or updates an env var. The value uses the unified string-value rules shared by every command: `"..."` or `'...'` quotes keep exact bytes (spaces, tabs), a lone `$var` evaluates that variable, `{{ ... }}` placeholders interpolate, unquoted words join with single spaces, and the first `=` splits key from value (`KEY=a=b` stores `a=b`). A `$var` inside larger text stays literal — write `{{ $var }}` to interpolate there.
**Arguments:**
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `assignment` | [`KEY=value`](#value-type-keyvalue) | yes | KEY=value pair |
**Examples:**
**Example: set env**
```oxdock
ENV APP_MODE=production
```
**Example: quoted value with spaces**
```oxdock
# quotes keep the space: SET_FORTH stores `outer scope`
ENV SET_FORTH="outer scope"
WRITE out.txt "{{ env:SET_FORTH }}"
ASSERT_FILE out.txt "outer scope"
```
**Example: variable value**
```oxdock
# a lone $var evaluates, like ECHO $var
LET $who = "Alice"
ENV GREETING=$who
WRITE out.txt "{{ env:GREETING }}"
ASSERT_FILE out.txt "Alice"
```
**Example: all value forms agree**
```oxdock
# a bare variable, a quoted literal, and a template all
# store plain strings through the same value rules
LET $x = "Ada"
ENV A=$x
ENV B="hello world"
ENV C="{{ $x }} concatenated"
WRITE check.txt "{{ env:A }}|{{ env:B }}|{{ env:C }}"
ASSERT_FILE check.txt "Ada|hello world|Ada concatenated"
```
**Example: scoped env reverts**
```oxdock
# ENV inside a braced block reverts when the block exits
ENV MODE=production
[bool:true] {
ENV MODE=staging
WRITE inner.txt "{{ env:MODE }}"
}
WRITE outer.txt "{{ env:MODE }}"
ASSERT_FILE inner.txt "staging"
ASSERT_FILE outer.txt "production"
```
### INHERIT_ENV
Inherit env vars from host.
**Syntax:** `INHERIT_ENV <key>...`
Declares which host environment variables to inherit into the script. Must appear before any other commands and at most once. Without this directive, the script starts with an empty environment.
**Arguments:**
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `keys` | [`string...`](#value-type-string) | no | Host variables to inherit |
**Examples:**
**Example: inherit env**
```oxdock
INHERIT_ENV [PATH, HOME]
```
### ECHO
Print to stdout.
**Syntax:** `ECHO <message>`
Outputs message to stdout.
**Arguments:**
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `message` | [`string...`](#value-type-string) | yes | Text |
**Output:** Stdout
**Examples:**
**Example: echo**
```oxdock
ECHO build-complete
```
**Example: variables**
```oxdock
# a lone $x evaluates; {{ }} interpolates inside text
LET $x = "World"
ECHO {{ $x }}
ECHO $x
ASSERT_STDOUT "World"
```
### RUN
Execute shell command.
**Syntax:** `RUN <command...>`
Runs command in cwd.
**Arguments:**
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `command` | [`string...`](#value-type-string) | yes | Command |
**Examples:**
**Example: run**
```oxdock
RUN echo hello
```
### COPY
Copy file into workspace.
**Syntax:** `COPY [--from-current-workspace] <from> <to>`
Copies from host.
**Arguments:**
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `from` | [`path`](#value-type-path) | yes | Source |
| `to` | [`path`](#value-type-path) | yes | Dest |
**Flags:**
| Flag | Type | Description |
| --- | --- | --- |
| `--from-current-workspace` | Flag | Copy from workspace instead of build context |
**Examples:**
**Example: copy**
```oxdock roots:unified
WRITE src.txt content
COPY src.txt dst.txt
ASSERT_FILE dst.txt content
```
**Example: copy from workspace**
```oxdock roots:unified
WRITE ws-src.txt ws-content
COPY --from-current-workspace ws-src.txt ws-copy.txt
ASSERT_FILE ws-copy.txt ws-content
```
### COPY_GIT
Copy from git revision.
**Syntax:** `COPY_GIT [--include-dirty] <rev> <src> <dst>`
Checkout and copy.
**Arguments:**
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `rev` | [`string`](#value-type-string) | yes | Rev |
| `src` | [`path`](#value-type-path) | yes | Src |
| `dst` | [`path`](#value-type-path) | yes | Dst |
**Flags:**
| Flag | Type | Description |
| --- | --- | --- |
| `--include-dirty` | Flag | Include dirty |
**Examples:**
**Example: git copy**
```oxdock expect_error:"COPY source missing"
COPY_GIT HEAD src.txt dst.txt
```
### SYMLINK
Create symlink.
**Syntax:** `SYMLINK <from> <to>`
Creates symlink.
**Arguments:**
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `from` | [`path`](#value-type-path) | yes | Target |
| `to` | [`path`](#value-type-path) | yes | Link |
**Examples:**
**Example: symlink**
```oxdock roots:unified
WRITE original.txt content
SYMLINK original.txt link.txt
ASSERT_FILE link.txt content
```
### MKDIR
Create directory.
**Syntax:** `MKDIR <path>`
Creates dir with parents.
**Arguments:**
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `path` | [`path`](#value-type-path) | yes | Dir path |
**Examples:**
**Example: mkdir**
```oxdock
MKDIR deeply/nested/tree
```
### LS
List directory.
**Syntax:** `LS [<path>]`
Lists entries.
**Arguments:**
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `path` | [`path`](#value-type-path) | no | Dir |
**Output:** Stdout
**Examples:**
**Example: ls**
```oxdock
MKDIR inventory
WRITE inventory/a.txt a
LS inventory
```
### CWD
Print working directory.
**Syntax:** `CWD`
Outputs cwd.
**Output:** Stdout
**Examples:**
**Example: cwd**
```oxdock
CWD
```
### READ
Read file to stdout.
**Syntax:** `READ [<path>]`
Outputs file contents.
**Arguments:**
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `path` | [`path`](#value-type-path) | no | File |
**Output:** Stdout
**Examples:**
**Example: read**
```oxdock
WRITE note.txt "hello"
READ note.txt
```
### READ_LINE
Read one line from stdin into a variable.
**Syntax:** `READ_LINE $var`
Reads bytes until newline without waiting for EOF, leaving the pipe open. Trailing newline is stripped (shell-read parity). On premature EOF assigns accumulated bytes and returns.
**Arguments:**
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `var` | [`$var`](#value-type-var) | yes | Variable to store the line |
**Examples:**
**Example: read line**
```oxdock
WITH_IO [stdout=pipe:lines] ECHO "first"
WITH_IO [stdin=pipe:lines] READ_LINE $reply
```
### WRITE
Write to file.
**Syntax:** `WRITE <path> [<contents>]`
Writes contents.
**Arguments:**
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `path` | [`path`](#value-type-path) | yes | File |
| `contents` | [`string...`](#value-type-string) | no | Content |
**Examples:**
**Example: write**
```oxdock
WRITE output.txt hello-world
```
### APPEND
Append to file.
**Syntax:** `APPEND <path> [<contents>]`
Appends contents.
**Arguments:**
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `path` | [`path`](#value-type-path) | yes | File |
| `contents` | [`string...`](#value-type-string) | no | Content |
**Examples:**
**Example: append**
```oxdock
WRITE log.txt line1
APPEND log.txt line2
ASSERT_FILE log.txt line1line2
```
### EXPAND
Expand a template file (or stdin) to stdout.
**Syntax:** `EXPAND [<path>] [<KEY=val> ...]`
A template is any text file — or piped stdin when no path is given — containing `{{ ... }}` placeholders. EXPAND replaces each placeholder and prints the result to stdout. Placeholders: `{{ NAME }}` reads a `KEY=val` override passed on this command; `{{ env:NAME }}` reads an override, falling back to the environment; `{{ $var }}` reads a script variable (dotted paths allowed). A missing key is an error, never a silent empty. A bare `$var` argument is a template path; `KEY=val` arguments are overrides whose values follow the unified string-value rules (same as `ENV`: quotes keep exact bytes, a lone `$var` evaluates, `{{ ... }}` interpolates). NOTE: `WRITE` interpolates `{{ ... }}` while writing, so escape it (`\{{ ... }}`) when writing a template file for a later `EXPAND`. With no path, the template arrives on stdin through a pipe. When piping from a shell, single-quote the template (`echo '{{ $x }}'`): double quotes let the shell swallow `$x`, so oxdock receives an empty `{{ }}` placeholder and errors.
**Arguments:**
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `path` | [`path`](#value-type-path) | no | Template file to expand; omit to expand stdin |
| `overrides` | [`KEY=value...`](#value-type-keyvalue) | no | Template overrides shadowing that key (unified string values) |
**Output:** Stdout
**Examples:**
**Example: expand**
```oxdock
ENV NAME="Alice"
WRITE template.md "Hello {{ env:NAME }}!"
EXPAND template.md
ASSERT_STDOUT "Hello Alice!"
```
**Example: override with spaces**
```oxdock
# WRITE would interpolate {{ }} right away, so escape it:
# the file must literally contain {{ env:NAME }} for EXPAND
WRITE template.md "Hello \{{ env:NAME }}!"
EXPAND template.md NAME="Alice Smith"
ASSERT_STDOUT "Hello Alice Smith!"
```
**Example: variable override**
```oxdock
# same escaping: keep the placeholder literal until EXPAND;
# a lone $who evaluates, like ECHO $who
LET $who = "Bob"
WRITE template.md "Hi \{{ env:WHO }}!"
EXPAND template.md WHO=$who
ASSERT_STDOUT "Hi Bob!"
```
**Example: override forms agree**
```oxdock
# a bare variable and a template-with-tail expand identically
LET $x = "Ada"
WRITE template.md "Hi \{{ env:NAME }} and \{{ env:NAME2 }}!"
EXPAND template.md NAME=$x NAME2="{{ $x }} concatenated"
ASSERT_STDOUT "Hi Ada and Ada concatenated!"
```
**Example: expand stdin**
```oxdock
# no path: the template arrives on stdin through a pipe
WITH_IO [stdout=pipe:tpl] ECHO "Hello \{{ env:NAME }}!"
WITH_IO [stdin=pipe:tpl] EXPAND NAME=Alice
ASSERT_STDOUT "Hello Alice!"
```
**Example: override does not leak**
```oxdock
# KEY=val overrides shadow env for that EXPAND only —
# they never update the environment itself
ENV NAME="Alice"
WRITE template.md "Hi \{{ env:NAME }}!"
EXPAND template.md NAME="Bob"
ASSERT_STDOUT "Hi Bob!"
EXPAND template.md
ASSERT_STDOUT "Hi Alice!"
```
### ASSERT_FILE
Assert file exists.
**Syntax:** `ASSERT_FILE [--hash <sha256>] <path> [<expected>]`
Checks the path is a file, then optionally compares its bytes (or `--hash` SHA-256 digest) against the expectation. Any mismatch aborts the pipeline with a step-numbered error showing expected vs actual.
**Arguments:**
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `path` | [`path`](#value-type-path) | yes | File |
| `expected` | [`string...`](#value-type-string) | no | Expected |
**Flags:**
| Flag | Type | Description |
| --- | --- | --- |
| `--hash` | String | SHA-256 |
**Examples:**
**Example: assert file**
```oxdock
WRITE payload.bin stable-content
ASSERT_FILE payload.bin stable-content
```
**Example: assert file hash**
```oxdock
# --hash compares the SHA-256 digest instead of raw bytes
WRITE payload.bin stable-content
ASSERT_FILE --hash 08135c1b6349b0e4f894c36221952f0de00e6b4d82f80895abf359755e77103c payload.bin
```
### ASSERT_DIR
Assert dir exists.
**Syntax:** `ASSERT_DIR <path>`
Checks the path is a directory, aborting the pipeline with a step-numbered error otherwise.
**Arguments:**
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `path` | [`path`](#value-type-path) | yes | Dir |
**Examples:**
**Example: assert dir**
```oxdock
MKDIR dist/assets
ASSERT_DIR dist/assets
```
### ASSERT_ABSENT
Assert path absent.
**Syntax:** `ASSERT_ABSENT <path>`
Checks nothing exists at the path, aborting the pipeline with a step-numbered error if it does.
**Arguments:**
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `path` | [`path`](#value-type-path) | yes | Path |
**Examples:**
**Example: assert absent**
```oxdock
ASSERT_ABSENT missing.txt
```
### ASSERT_STDOUT
Assert stdout contains.
**Syntax:** `ASSERT_STDOUT <substring>`
Checks the preceding step's stdout contains the substring, aborting the pipeline with a step-numbered error otherwise.
**Arguments:**
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `substring` | [`string...`](#value-type-string) | yes | Substring |
**Examples:**
**Example: assert stdout**
```oxdock
ECHO build-complete
ASSERT_STDOUT build-complete
```
### HASH_SHA256
Print SHA-256.
**Syntax:** `HASH_SHA256 <path>`
Computes digest.
**Arguments:**
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `path` | [`path`](#value-type-path) | yes | File |
**Output:** Stdout
**Examples:**
**Example: hash**
```oxdock
WRITE payload.txt hello
HASH_SHA256 payload.txt
```
### EXIT
Exit pipeline.
**Syntax:** `EXIT <code>`
Stops the pipeline immediately with an `EXIT requested with code <code>` error; steps after it never run, at any nesting depth. Enclosing blocks still unwind their LET/ENV/WORKDIR/WORKSPACE state, anonymous background tasks are killed synchronously, and files written before the EXIT persist.
**Arguments:**
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `code` | [`int`](#value-type-int) | yes | Code |
**Examples:**
**Example: exit**
```oxdock expect_error:"EXIT requested with code 0"
EXIT 0
```
### SLEEP
Pause execution for a duration.
**Syntax:** `SLEEP <duration>`
Parks the step for the duration (e.g. 500ms, 10s, 2m). Cooperative: checks for cancellation so an enclosing TIMEOUT or task teardown interrupts the sleep. Cross-platform alternative to shell sleep for testing time boundaries.
**Arguments:**
| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `duration` | [`duration`](#value-type-duration) | yes | How long to sleep |
**Examples:**
**Example: sleep**
```oxdock
SLEEP 100ms
```
**Example: sleep variable duration**
```oxdock
# durations resolve at runtime, so variables work too —
# quoted or bare, both bind the same string
LET $pause = "100ms"
SLEEP $pause
LET $bare = 100ms
SLEEP $bare
```
## Value types
### Value type: string
Arbitrary text under the unified string-value rules: quotes keep exact bytes, a lone `$var` evaluates, and `{{ ... }}` placeholders interpolate.
### Value type: path
Workspace path, resolved against the current working directory and guarded against escaping the workspace.
### Value type: int
Integer, e.g. an exit code.
### Value type: duration
Positive time span: a number with an `ms`, `s`, `m`, or `h` suffix — a bare number means seconds — e.g. `500ms`, `10s`, `2m`.
### Value type: $var
Script variable reference. The `$` sigil is mandatory.
### Value type: KEY=value
`KEY=value` assignment splitting on the first `=` (`KEY=a=b` stores `a=b`). Values follow the unified string-value rules.