⚠️ mlld is pre-release
Join the discord if you have questions. Report bugs on GitHub.
Working with Large Variables
mlld can handle large amounts of data like entire codebases. Node.js has limits when passing large variables to commands (typically around ~128KB–200KB for args+env). mlld now automatically falls back to a safe shell mode for large payloads to avoid these limits.
tldr
Use shell mode for large data (mlld will auto-fallback when needed):
>> This usually works automatically now, but explicit shell mode is recommended for clarity when dealing with large data
/run sh (@largefile) { echo "$largefile" | grep "TODO" }
>> This works with any size
/run sh (@largefile) { echo "$largefile" | grep "TODO" }
The Problem
Node.js can't pass variables larger than ~128KB to commands - it throws an E2BIG error. This happens when loading many files:
>> Load entire codebase (could be megabytes)
/var @allCode = <**/*.js>
>> Previously, this could error if @allCode > 128KB. mlld now auto-falls back to shell when needed.
/run sh (@allCode) { echo "$allCode" | wc -l }
The Solution
Use Shell Mode
Switch from simple /run cmd {...} to shell mode /run sh {...} when writing workflows, even though mlld auto-fallbacks, because:
- It’s explicit about using
$varsyntax inside the block - It avoids implicit fallback and makes intent clear in reviews
>> Simple run - limited to ~128KB, uses @var syntax
/run cmd {tool "@data"}
>> Shell mode - handles any size, pass params then use $var syntax
/run sh (@data) { echo "$data" | tool }
Important syntax difference:
- Simple
/run cmd {...}interpolates mlld variables with@varsyntax - Shell
/run sh (@var) {...}declares parameters in parentheses, then uses$varsyntax inside
For Executables
Define executables with bash or sh to handle large data:
>> Load entire codebase
/var @contracts = <**/*.sol>
>> Process with shell executable - parameter becomes shell variable
/exe @analyze(code) = sh {
echo "$code" | solidity-analyzer
}
>> Pass the mlld variable when calling
/show @analyze(@contracts)
The key: shell mode receives mlld variables as parameters (declared in parentheses), then accesses them as shell variables with $ inside the code block.
Working with External Tools
Pipe data to tools instead of passing as arguments:
>> Good pattern for large data
/exe @process(content) = sh {
echo "$content" | jq '.items[]'
}
>> Load many files
/var @configs = <**/*.json>
/show @process(@configs)
How It Works
- Simple
/run cmd {...}now auto-falls back to bash when command/env payloads are large. The script is streamed via stdin to avoid args+env limits. - Shell mode
/run sh {...}injects large variables directly into the shell script instead of the environment (via heredoc), bypassing Node's limit. - Your variables work the same - just use
$varnamein shell mode.
To disable auto-fallback (for debugging/policy), set MLLD_DISABLE_SH=1. In that mode, /run is strict and will error with guidance when payloads are too large.
When You'll Hit This
Common scenarios that exceed 128KB:
- Loading all source files:
<**/*.js> - Processing large JSON files
- Working with documentation:
<docs/**/*.md> - Analyzing entire codebases
Error Messages
With the default auto-fallback, you should rarely see size-related errors. If MLLD_DISABLE_SH=1 is set, /run will be strict and show helpful guidance when payloads are too large.