output writes to files and stdout. log writes to stderr. append adds to existing files. stream enables real-time token-by-token output from LLM calls.
Output Directive
output @content to "out.txt"
output @data to "config.json"
output @message to stdout
output @error to stderr
Objects and arrays are automatically serialized to JSON when writing to .json files. For other file types, the value is converted to a string.
See Also
- Append Directive - Append structured or text output incrementally.
- Log Directive - Emit output to stderr.
- Pipelines Basics - Attach
outputas a pipeline effect stage.
Log Directive
var @debugMode = true
log @message >> same as output @message to stderr
log `Processing: @item`
>> In action contexts
for @item in @items => log @item
when @debugMode => log "Debug info"
See Also
- Output Directive - File/stdout/stderr output patterns and formatting.
- Pipelines Basics - Use
| logas a pipeline effect stage.
Append Directive
append @record to "events.jsonl" >> JSON object per line
append "raw line" to "events.log"
>> In pipelines
var @_ = @data | append "audit.jsonl"
>> In loops
for @name in @runs => append @name to "pipeline.log"
.jsonl enforces JSON serialization. Other extensions write text. .json blocked.
Streaming
>> In definition (recommended)
exe @llm(prompt) = stream cmd {
claude -p "@prompt" --output-format stream-json --verbose --include-partial-messages
} with { streamFormat: "claude-code" }
show @llm("Explain TCP/IP") >> streams tokens as they arrive
>> At invocation
exe @raw(prompt) = cmd {claude -p "@prompt" --output-format stream-json --verbose --include-partial-messages}
run stream @raw("Hello") with { streamFormat: "claude-code" }
Definition-level stream and streamFormat are inherited by both run @exe() and show @exe().
import { @haiku } from @mlld/claude-stream
show @haiku("Explain TCP/IP") >> streams + parses by default
Format Adapters
NDJSON streams require a format adapter to parse and display incrementally.
>> Built-in adapter (string shorthand)
run stream @exe("prompt") with { streamFormat: "claude-code" }
>> Installable adapter
import { @claudeAgentSdkAdapter } from @mlld/stream-claude-agent-sdk
run stream @exe("prompt") with { streamFormat: @claudeAgentSdkAdapter }
| Adapter | Aliases | Parses |
|---|---|---|
ndjson |
— | Generic NDJSON (default) |
claude-code |
claude-agent-sdk |
Claude CLI stream-json events |
Without an adapter, raw NDJSON passes through unformatted.
Shell Streaming
Non-NDJSON commands stream raw stdout:
exe @build() = stream sh {npm run build}
show @build() >> live build output
Parallel
stream @a() || stream @b() >> concurrent, buffered per-task
Suppress
mlld script.mld --no-stream
MLLD_NO_STREAM=true mlld script.mld
Debug
mlld script.mld --show-json >> mirror NDJSON to stderr
mlld script.mld --append-json out.jsonl >> save events to file
Limitations
- After-guards conflict with streaming (output must be complete for validation)
- Pipeline stages buffer between stages; streaming is within each stage