In strict mode (.mld), directives are bare keywords. In markdown mode (.mld.md), prefix with `/`. ```mlld >> Strict mode var @greeting = `Hello @name!` show @greeting >> What NOT to do Hello @name! Let me show something. >> This is an error in strict mode ``` Create with `var @name = value`. Reference with `@name` in templates/commands. ```mlld var @name = "Alice" show `Hello @name!` run cmd {echo "User: @name"} run js (@name) { console.log("Hi", name) } ``` Every command needs braces. Use language specifiers: `cmd {}` for simple commands, `sh {}` for shell scripts, `js {}` for code. ```mlld >> Language specifiers run cmd {echo "hello"} >> simple commands (pipes only) run sh {npm test && build} >> shell scripts (&&, ||, multi-line) run js {console.log("hi")} >> JavaScript code >> Executables exe @hi() = cmd {echo hi} exe @script() = sh { echo "multi"; ls -la } exe @calc(x) = js { return x * 2 } ``` Only these produce output: `show`, `run`, `output`. Everything else mutates state. ```mlld var @secret = "hidden" >> no output show `Visible` run cmd {echo "Also visible"} ``` Default to `::...::` or backticks for templates. Use `@var` for interpolation. | Syntax | Interpolation | Use For | |--------|---------------|---------| | `` `...` `` | `@var` `` | Default inline | | `::...::` | `@var` `` | When backticks in text | | `"..."` | `@var` `` | Single-line only | | `'...'` | None (literal) | Literal text | | `{...}` | `@var` `` | Commands/code | ```mlld >> Backticks (default) var @msg = `Hello @name!` >> Double-colon (when text has backticks) var @doc = ::Use `npm test` before @env:: >> Double quotes (single-line) var @path = "@base/files/@filename" >> Single quotes (literal - no interpolation) var @literal = '@name stays literal' ``` Loops work inside templates: ```mlld var @list = ` for @item in @items - @item.name: @item.value end ` ``` Objects/arrays use dot notation. Arrays support slicing. Methods available on values. ```mlld var @user = {"name":"Alice","scores":[10,20,30]} show @user.name >> Alice show @user.scores.1 >> 20 >> Array slicing var @arr = [1,2,3,4,5] show @arr[0:3] >> [1,2,3] show @arr[-2:] >> [4,5] - last 2 >> Builtin methods var @list = ["apple", "banana"] show @list.includes("banana") >> true show @list.join(", ") >> "apple, banana" var @text = "Hello World" show @text.toLowerCase() >> "hello world" show @text.split(" ") >> ["Hello", "World"] show @text.trim().startsWith("H") >> true (chained) ``` Use `exe` for reusable templates, commands, or complex logic with blocks. ```mlld >> Simple template exe @greet(name) = `Hello @name!` show @greet("Bob") >> Command exe @list(dir) = cmd {ls -la @dir | head -5} >> Block syntax for multi-statement bodies exe @process(data) = [ let @validated = @validate(@data) let @transformed = @transform(@validated) => @transformed ] ``` Angle brackets load file contents. Works with globs and AST selectors. ```mlld var @content = >> file contents var @config = >> parsed as object var @author = .author >> field access >> Globs var @docs = show @docs.length >> number of files for @doc in @docs => show @doc.mx.filename >> AST selectors (code extraction) var @funcs = >> all functions var @handler = >> specific function ``` Detection rule: only `<…>` with `.`, `/`, `*`, or `@` are file refs. XML-like `` is plain text. Module imports for code reuse. Namespace imports avoid collisions. ```mlld >> Registry modules import { @parallel, @retry } from @mlld/core import @corp/utils as @corp >> Local files import { @helper } from "./utils.mld" import { @config } from <@base/config.mld> >> Import types import module { @api } from @corp/tools >> cached import static { @prompt } from "./prompt.md" >> embedded at parse import live as @status >> always fresh >> Directory imports import "@agents" as @agentRegistry show @agentRegistry.alice.tldr ``` `when` for conditionals. Use `first` for switch-style (stops at first match). ```mlld >> Simple condition when @isProd => show "Production mode" >> Switch-style (first match wins) when first [ @role == "admin" => show "Admin" @role == "user" => show "User" * => show "Guest" ] >> Bare when (evaluates all matches) when [ @score > 90 => show "Excellent!" @hasBonus => show "Bonus earned!" none => show "No matches" ] ``` `foreach` transforms collections. `for` executes or collects. ```mlld >> foreach (transform array) var @names = ["alice", "bob"] exe @greet(name) = `Hi @name!` var @greetings = foreach @greet(@names) >> for (execute per item) for @n in @names => show `Name: @n` >> for (collect results) var @doubled = for @x in [1,2,3] => @x * 2 >> for with block syntax for @item in @items [ let @processed = @transform(@item) show `Done: @processed` ] >> Parallel execution for parallel(3) @task in @tasks => @runTask(@task) >> For with inline filter var @valid = for @x in @items when @x != null => @x ``` Logical, comparison, and ternary operators. ```mlld >> Comparison: <, >, <=, >=, ==, != >> Logical: &&, ||, ! >> Ternary: condition ? trueVal : falseVal var @isValid = @score > 80 && @submitted var @status = @isPro ? "premium" : "basic" var @canEdit = @isOwner || (@role == "editor" && !@isLocked) >> In conditions when @tokens > 1000 && @mode == "production" => show "High usage" ``` State updates via `state://` protocol. SDK captures writes without filesystem I/O. ```mlld var @count = @state.count + 1 output @count to "state://count" ``` ```typescript // SDK provides state, captures writes execute(file, payload, { state: { count: 0 } }); // Returns: { stateWrites: [{ path: 'count', value: 1 }] } ```