# leumas-lmx

Write, run or extend an LMX script — the 16 interpreters, incl. lma (call any tool), lmi (ask the install), lmq (query), lmai (model), lmg (grids). Read before writing one or adding a mode.


# Writing LMX

LMX (`shared/engines/lmx`, `@leumas/lmx`) runs **16 small languages** in a sandboxed, time-bounded
worker thread. Nine are general computing. **Five speak Leumas**, and two of those are *dynamic* —
their vocabulary is a live registry, so what they can do grows with the ecosystem:

| Want to… | Use | Needs |
|---|---|---|
| **call any tool this install has** | **`lma`** dynamic | the `tools` bridge → `POST /api/lmx/run` |
| **ask what this deployment can do** | **`lmi`** dynamic | the `install` bridge → `POST /api/lmx/run` |
| read stored rows | `lmq` | the `db` bridge |
| drive a language model | `lmai` | the `ai` bridge |
| compose a programming grid | `lmg` | nothing — runs anywhere |
| general logic + one adapter call | `lmx` | `adapters` for `adapter()` |
| a quick calculation | `lmy` · `lmm` · `lmc` | |
| events, notifications | `lmz` · `lmn` | |
| shell, GUI, network, timers | `lms` `lmk` `lmd` `lmnet` `lmt` | **admin + an env flag** |

Full generated list with syntax and snippets: `shared/engines/lmx/src/INTERPRETERS.md`.
Deep references: **`reference/lma.md`** · **`reference/lmi.md`** · **`reference/lmq.md`** ·
**`reference/lmai.md`** · **`reference/lmg.md`**.

## Reach for `lma` first

Before writing a bespoke script, remember `lma` can already call every adapter tool, every stored
functioncall and user integration, every automation action, every MCP tool and every vendor-neutral
capability — ~1,800 verbs, resolved live:

```lma
PLANES                                      # what planes exist here
DISCOVER "invoice"                          # search all of them
DESCRIBE a-text.Base64Encode                # declared params
USE a-text.Base64Encode { "text": "{{input}}" } -> e
EACH row IN rows USE a-text.Summarize { "text": "{{row.body}}" } -> summaries
TRACE                                       # what actually ran, and which provider served a cap:
```

And `lmi` answers *"what can this install do"* rather than *"what can Leumas do"*:

```lmi
INSTALL
CAN ai.text.generate            # this USER's entitlement, three-state
PROVIDERS FOR email.send        # who would actually serve it here
LIST tools WHERE category = "media" LIMIT 20
```

## Run one

```bash
leumas-lmx ./script.lmg                     # lmg and the general modes need no host
curl -s -X POST localhost:3000/api/lmx/run -H 'content-type: application/json' \
  -d '{"mode":"lmi","source":"INSTALL"}'    # lma/lmi/lmq/lmai need bridges
```

`GET /api/lmx/interpreters` is the live catalog for a given install; `GET /api/lmx/demos` returns the
bundled scripts with source — the fastest working example of any mode.

## The six traps

1. [critical] **An `lmai` reply is not proof a model ran.** `resolve()` never fails — `auto` falls back to an
   echo stub. Branch on `usage.stub`. Worst case, verified live: a shaped ask on the stub returns your
   own `SHAPE` example as a flawless-looking answer, with `stub:true, tokens:0` the only tell.
2. [critical] **`lmi` must never answer "yes" by default.** No entitlement engine wired ⇒ `unknown`, never
   `true`. An unknown reported as yes is a confident wrong claim about someone else's deployment.
3. [critical] **Entitled ≠ fulfillable.** `CAN` and `PROVIDERS FOR` are different questions; a user can be
   entitled to a capability this install has nothing connected to serve.
4. [critical] **`lmg` cells go in `specialConfig`, not `props`.** Both execute; only `specialConfig` (and a
   top-level `code`) is read by the dependency graph, so a props-authored grid prints an empty `GRAPH`.
5. **`lmq` timestamps are epoch milliseconds.** Use `days_ago(n)`, not a date string.
6. **A bridge-needing mode REFUSES without its bridge** rather than returning empty. *"needs the …
   bridge"* means you are on the CLI or the `lmx` adapter — use `POST /api/lmx/run`.

## What bounds a script

Everything a script can reach is a **named channel** the host wired. Nothing else escapes the worker.

| Channel | For | Bounded by |
|---|---|---|
| `adapter` | the `adapter()` builtin | — *(unmetered; see below)* |
| `db` | `lmq` | read-only by construction · `/db`'s deny lists · per-row `canRead` · 5000 rows |
| `ai` | `lmai` | `resolveKeyForUser` · 20 calls · 60s |
| `tools` | `lma` | host scope + `USING` · 50 calls · `passnode.charge` · 30s |
| `install` | `lmi` | read-only; there is no method that changes anything |

All are **factories** called per request with `req.user`. Never cache one across users.

[critical] **Metering asymmetry.** `/api/adapters/:system/:fn` is priced by `passnode.guard`, but that lives in
the HTTP router — `registry.run()` is not metered, so non-HTTP callers are free. `lma` closes this for
itself by charging the same `tool:` target; the older `adapter()` builtin is still unmetered.

## Adding an interpreter

| File | Add |
|---|---|
| `src/interpreters/<id>/{index,parser,runner}.js` | `run({ filename, source, bridges, inputs })` |
| `src/host/interpreters.catalog.js` | one entry — lights up the API, Playground, tooltips and Reference tab |
| `src/host/worker.js` | one `case` in `dispatch()` (+ a channel proxy if it needs one) |
| `src/host/demos.js` | one `EXT_TO_MODE` entry |
| `src/index.js` | `resolveMode()` + CLI dispatch |

**Prefer a dynamic design.** If the new language needs a vocabulary, ask whether a registry already
holds it — `planes.js` turns any registry's exported functions into verbs, and `install.js` takes the
index-service source map. A language built that way never goes stale. Put policy in the *mounting
app*, never in the engine: `@leumas/lmx` depends only on `express` and `@leumas/grids`.

Then a demo in `src/scripts/`, a case in `ops/infra/scripts/check-lmx.mjs`, tests in `src/test/`, and

```bash
pnpm docs:lmx        # regenerate INTERPRETERS.md from the catalog
pnpm smoke:lmx       # every safe mode, every bridge, every gate, + docs drift
node --test src/test/*.test.js
pnpm skills:sync && pnpm check:skills
```

`INTERPRETERS.md` is **generated**. Editing it by hand is how it came to document 7 of 11 modes.


---
Source: .claude/skills/leumas-lmx/SKILL.md
Canonical: https://docs.leumas.tech/p/skills/leumas-lmx
