Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"name": "lua-agent-builder",
"source": "./plugins/lua-agent-builder",
"description": "Build, test, and deploy Lua AI agents from inside Claude Code",
"version": "1.12.0",
"version": "1.13.0",
"homepage": "https://github.com/lua-ai-global/claude-code-lua-plugin#readme",
"repository": "https://github.com/lua-ai-global/claude-code-lua-plugin.git",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Then `/lua-auth`: an existing credential is kept; a new login runs `lua auth con

| Plugin | Description |
|---|---|
| [`lua-agent-builder`](./plugins/lua-agent-builder/) | 23 slash commands, 10 subagents, 13 hooks, a 9-file knowledge base verified against lua-cli source (3.33.0 base; 1.3.0 added per-step model classes and the workflow autonomy envelope from lua-cli 3.36.0, 1.4.0 the Job-tier billing rules and the lua-cli 3.37.0 cost read-outs, 1.5.0 log drains and the `lua logs` read window from lua-cli 3.38.0, read from `main`; 1.6.0 headless mode and a hardened production-gate parser; 1.7.0 `/lua-devices`, device credentials that never reach the conversation, and a re-check against lua-cli 3.44.0 / 3.45.0; 1.8.0 web apps (Lua Apps); 1.9.0 the full QA suite, `/lua-qa full`; 1.10.0 decisions, `/lua-decisions` and `/lua-new decision` from lua-cli 3.48.0 / 3.49.2; 1.11.0 `/lua-deploy webapp` scoped web-app deploys from lua-cli 3.49.0; 1.12.0 org-shared `Data.shared` and web-app viewer decisions from lua-cli 3.50.0), a local read-only platform MCP server and the public docs MCP |
| [`lua-agent-builder`](./plugins/lua-agent-builder/) | 23 slash commands, 10 subagents, 13 hooks, a 9-file knowledge base verified against lua-cli source (3.33.0 base; 1.3.0 added per-step model classes and the workflow autonomy envelope from lua-cli 3.36.0, 1.4.0 the Job-tier billing rules and the lua-cli 3.37.0 cost read-outs, 1.5.0 log drains and the `lua logs` read window from lua-cli 3.38.0, read from `main`; 1.6.0 headless mode and a hardened production-gate parser; 1.7.0 `/lua-devices`, device credentials that never reach the conversation, and a re-check against lua-cli 3.44.0 / 3.45.0; 1.8.0 web apps (Lua Apps); 1.9.0 the full QA suite, `/lua-qa full`; 1.10.0 decisions, `/lua-decisions` and `/lua-new decision` from lua-cli 3.48.0 / 3.49.2; 1.11.0 `/lua-deploy webapp` scoped web-app deploys from lua-cli 3.49.0; 1.12.0 org-shared `Data.shared` and web-app viewer decisions from lua-cli 3.50.0; 1.13.0 `lua apps preview` from lua-cli 3.51.0), a local read-only platform MCP server and the public docs MCP |

## Quick walkthrough

Expand Down
2 changes: 2 additions & 0 deletions docs/USER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ If you just want to start: [Installation](#installation) → [Your first agent](

`/lua-doctor` checks all of these and offers consent-gated fixes. Platforms: macOS 14+, Ubuntu 22.04+, Windows 11; CI runs the suite on all three with Node 18 and 20.

New in 1.13.0: **preview a web app before it goes live.** After `/lua-push webapp`, the builder can open the staged version with `lua apps preview`: a Lua Workspace link on its own address, where Data writes go to a throwaway copy, emails and messages are recorded instead of sent, and outside calls are blocked. Anyone who can edit the agent can open it, for 24 hours by default. Needs lua-cli 3.51.0.

New in 1.12.0: **org-shared Data and viewer decisions.** When several agents of one organization need the same dataset, the builder now recommends `Data.shared(name)` (same methods as `Data`; an org admin creates the collection and names its readers and writers through the admin API) and explains its errors, including why every call fails in a local test run. A web app's routes can decide workflow approvals and answer input steps as the signed-in person with `Workflows.viewer`. Needs lua-cli 3.50.0.

New in 1.10.0: **decisions.** A decision is one call that takes some state and typed questions and returns typed answers with probabilities: the odds that something is true, a choice with its confidence, or a score on a scale. `/lua-new decision <name>` writes a `LuaDecision` with literal questions and registers it; `/lua-push decision` stages a version; `/lua-decisions` lists the agent's decisions, shows their versions, runs one on a message or JSON state (on the version's model, or `--model <id>` for any of the thirteen decision models, Jev and OpenAI included), publishes a version (the rollback) or deletes one. Reads and runs go at once; publish and delete confirm once through the Bash prompt. Needs lua-cli 3.48.0; `--model` and the OpenRouter ids need 3.49.2.
Expand Down
2 changes: 1 addition & 1 deletion plugins/lua-agent-builder/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "lua-agent-builder",
"version": "1.12.0",
"version": "1.13.0",
"description": "Build, test, and deploy Lua AI agents from inside Claude Code",
"author": {
"name": "Lua AI",
Expand Down
12 changes: 12 additions & 0 deletions plugins/lua-agent-builder/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@

All notable changes to the `lua-agent-builder` plugin. Versions follow the tag `release-prod.yml` cuts from `package.json` (`v<version>`). lua-cli is a TypeScript SDK/CLI; it is unrelated to the Lua programming language.

## 1.13.0 — 2026-10-12

**Preview a web app version before it is live** (lua-cli 3.51.0).

### Changed

- **`web-apps.md` §7a: `lua apps preview`.** Opening a staged version as a Lua Workspace link on its own origin (`<slug>--p-<id>`) under a Preview banner; what a preview isolates — Data writes go to a copy deleted at the end, emails and messages are recorded (`--effects`), `fetch` fails with `TEST_EGRESS_BLOCKED` and is not recorded, `env()` works, `Products`/`Baskets`/`Orders`/`Templates`/`CDN`/`Jobs` answer `test_session_tier_unsupported`, `Workflows.viewer` answers `viewer_unavailable`; who can open it (edit access), `--ttl` (24 h, max 168 h), `--list`/`--close`/`--effects`, `PREVIEW_ENDED`, `WEB_APP_PREVIEW_NEEDS_AGENT_VERSION`, exit codes. §9 gains the "works in `lua test webapp`, errors in a preview" row.
- **`/lua-push webapp`** offers the preview after a push on lua-cli 3.51.0+ and runs it only if the user wants the link. **`/lua-deploy`** mentions it for a version the user is unsure about. A preview is never reported as deployed.
- `scripts/lint-knowledge-commands.mjs`: `lua apps` gains `preview` (and the existing `delete`).

`lua apps preview` sits in no permission list: Claude Code asks once before it runs (it opens a shareable link). `PINNED_MIN_LUA_CLI` is unchanged: the new section is marked lua-cli 3.51.0+.

## 1.12.0 — 2026-10-11

**Org-shared Data and viewer decisions from web apps** (lua-cli 3.50.0).
Expand Down
2 changes: 1 addition & 1 deletion plugins/lua-agent-builder/commands/lua-deploy.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ If `$ARGUMENTS` already names a target and name/version, pre-fill them. AskUserQ

- "What goes live?" (options: `skill`, `webhook`, `trigger`, `job`, `preprocessor`, `postprocessor`, `persona`, `workflow`, `webapp` (⏳ lua-cli 3.49.0+: goes live on its own; below: through a new agent version — only the web app may change), `mcp`, `voice`, `agent-version` (promote a whole-agent snapshot — also how you roll back), `all` (latest version of every deployable primitive))

⏳ From lua-cli **3.49.0** a web app deploys like a webhook: `webapp` pushes it and runs `lua deploy webapp`, a scoped promote that moves only that app's pin. Below 3.49.0 there is no `webapp` deploy type: `webapp` pushes it and promotes a new agent version that differs from the live one only in its web apps (`lib/knowledge/web-apps.md` §7). Devices and device-triggers are **not** deployed here: they are not part of agent versions, a pushed `defineDevice` is live on the next turn, and a device-trigger is published only by `--auto-deploy`, which this plugin never runs. If the user names one, say so and point at `/lua-devices push` (`lib/knowledge/devices.md` §5) instead of asking.
⏳ From lua-cli **3.49.0** a web app deploys like a webhook: `webapp` pushes it and runs `lua deploy webapp`, a scoped promote that moves only that app's pin. Below 3.49.0 there is no `webapp` deploy type: `webapp` pushes it and promotes a new agent version that differs from the live one only in its web apps (`lib/knowledge/web-apps.md` §7). ⏳ On lua-cli 3.51.0+ a staged version can be clicked through first with `lua apps preview <name>` (§7a) — not a deploy, nothing goes live; mention it when the user is unsure the version is ready. Devices and device-triggers are **not** deployed here: they are not part of agent versions, a pushed `defineDevice` is live on the next turn, and a device-trigger is published only by `--auto-deploy`, which this plugin never runs. If the user names one, say so and point at `/lua-devices push` (`lib/knowledge/devices.md` §5) instead of asking.
- "Name?" (free-text; hidden for `persona`, `all`, `agent-version`). If `dist-v2/manifest.json` exists, pre-offer names of the matching kind.
- "Version?" (options: `latest`, or free-text `x.y.z` — an integer for `persona`, an agent version number for `agent-version`; hidden for `mcp` and `all`)
- "Notes? (optional — e.g. 'activate the workflow schedule', a version message)" (free-text)
Expand Down
2 changes: 1 addition & 1 deletion plugins/lua-agent-builder/commands/lua-push.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Always `--ci --force`. **NEVER** `--auto-deploy` (denied at the permission layer

⚠ A failed item: below lua-cli 3.44.0, `all` (and a type push of several primitives) prints `❌ Failed to push <name>: …` per item and `⚠️ N component(s) failed to push`, then `✅ Push All Complete!`, and still **exits 0**; ⏳ from 3.44.0 it exits 1 when any item failed (`push.ts` `pushAllExitCode`). Either way scan the output for `❌ Failed to push`; if present, report the failed items as a failure (the others were pushed) — never say "✓ Pushed".

On success: "✓ Pushed `<type>:<name>` v`<version>` (server version created; not live). Next: `/lua-deploy`." — for workflows note the live path is `lua workflows deploy <name> -v latest` (the deploy slash handles it); for `agent` say plainly that the model settings are **already live** and, on 3.44.0 or later, that persona v`<n>` is **staged** (`/lua-deploy` persona makes it live) — below 3.44.0 that it is already live (rollback: `/lua-deploy` persona with the previous version); for `device` say it is **live on the next turn** (rollback = push the previous code); for `device-trigger` print the user-terminal `--auto-deploy` line; for `webapp` the CLI ends with `Staged but NOT live yet` — say it is staged and that `/lua-deploy webapp` makes it live (⏳ lua-cli 3.49.0+: on its own, nothing else staged goes live; below: through an agent version, or ship it with `agent-version`), then it opens at `https://workspace.heylua.ai/apps/<agent.agentId from lua.skill.yaml>/<name>`; for `all` add that every `defineDevice` is live and the other primitives still need `lua deploy` / an agent version promote.
On success: "✓ Pushed `<type>:<name>` v`<version>` (server version created; not live). Next: `/lua-deploy`." — for workflows note the live path is `lua workflows deploy <name> -v latest` (the deploy slash handles it); for `agent` say plainly that the model settings are **already live** and, on 3.44.0 or later, that persona v`<n>` is **staged** (`/lua-deploy` persona makes it live) — below 3.44.0 that it is already live (rollback: `/lua-deploy` persona with the previous version); for `device` say it is **live on the next turn** (rollback = push the previous code); for `device-trigger` print the user-terminal `--auto-deploy` line; for `webapp` the CLI ends with `Staged but NOT live yet` — say it is staged and that `/lua-deploy webapp` makes it live (⏳ lua-cli 3.49.0+: on its own, nothing else staged goes live; below: through an agent version, or ship it with `agent-version`), then it opens at `https://workspace.heylua.ai/apps/<agent.agentId from lua.skill.yaml>/<name>`; ⏳ on lua-cli 3.51.0+ also offer to click through the staged version first with `lua apps preview --ci <name>` (a Workspace link on its own address; Data writes go to a copy, emails and messages are recorded, `fetch` fails — `lib/knowledge/web-apps.md` §7a), and run it only if the user wants the link; for `all` add that every `defineDevice` is live and the other primitives still need `lua deploy` / an agent version promote.

If the output contains `Model configuration cleared`, `Model settings cleared`, `Batching config cleared` or `Voices cleared` (types `all` / `agent`), say so plainly: the agent push overwrites those server fields with whatever `src/index.ts` declares, so a model chosen in the dashboard is now gone. Point at the fix: set `model` (or `modelSettings` / `batching`) on the `LuaAgent` — `lua models set --model <code>` writes it for you — and push `agent` again.

Expand Down
20 changes: 19 additions & 1 deletion plugins/lua-agent-builder/lib/knowledge/web-apps.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Web apps — pages and typed routes on an agent (lua-cli 3.42.0+ · read at 3.45.0; §7 deploy at 3.49.0)
# Web apps — pages and typed routes on an agent (lua-cli 3.42.0+ · read at 3.45.0; §7 deploy at 3.49.0; §7a preview at 3.51.0)

Read from lua-cli `src/types/web-app.ts`, `src/commands/apps.ts`, `src/commands/test.ts` (`testWebApp`), `src/commands/push.ts`, `src/primitives/web-app.handler.ts`, `src/utils/web-app-build.ts`, `src/utils/web-app-route.ts` and `template-web-app/` at **3.45.0** (npm `latest` is 3.46.0 on 2026-10-06 — not re-read); the wire contract and limits from `@lua/shared-types` `web-route-contract.ts`; the page policy from lua-core `src/apps-gateway/web-app-html.ts`; the snapshot rule from lua-agents `agent-version.service.ts`. Product docs: docs.heylua.ai `/concepts/apps`, `/build/apps/quickstart`, `/build/apps/routes-and-pages`, `/reference/cli/apps`. Below lua-cli **3.42.0** `webapp` is not a push/test type and `lua apps` does not exist — `/lua-update` first.

Expand Down Expand Up @@ -104,6 +104,23 @@ Compiles, then starts the app's own Vite with hot reload; routes are served at `
| Roll back | 3.49.0+: `LUA_DEPLOY_CONFIRMED=1 lua deploy webapp --ci --name <app> --set-version <previous> --force`; any version: promote an earlier agent version | the scoped form rolls back only that app |
| Switch off | admin console → agent → Apps | an admin toggle; a disabled app answers `APP_DISABLED`. A deploy **never** switches it on: 3.49.0+ prints `⚠️ Web app <app> is switched off: the new version is live, but nobody can open it until it is switched on again.` — pass that on |

### 7a. Preview a staged version before it is live — `lua apps preview` (⏳ lua-cli 3.51.0+)

Read from lua-cli `src/commands/apps-preview.ts` and lua-core `src/apps-gateway/web-app-preview.service.ts` on `main` (ADR 0019); docs.heylua.ai `/reference/cli/apps#lua-apps-preview`.

```
lua apps preview --ci <name> [--version <v>|latest] [--ttl 24h|2d] [--json] # open one (or get the open one for that version)
lua apps preview --ci [<name>] --list | --close <id> | --effects <id>
```

- Prints a **Lua Workspace link** (`https://workspace.heylua.ai/apps/<agentId>/<name>?preview=<id>`) to that pushed version, framed on its **own origin** `<slug>--p-<id>.apps.heylua.ai` under a **Preview** banner. Any version can be previewed (default: the latest push); a disabled app or one with no live version too. A second open of the same version hands back the open preview.
- **Isolated:** routes read the agent's `Data`, but every write, update and delete goes to a **copy** (copy-on-write) deleted when the preview ends. Emails and messages are **recorded, not sent** (`--effects <id>` lists them, needs `logs:read`). ⚠ A `fetch` (any outside network call) **fails with `TEST_EGRESS_BLOCKED`** and is not recorded — a route that calls a third party errors in a preview. `env()` works. `Products`, `Baskets`, `Orders`, `Templates`, `CDN` and `Jobs` answer `test_session_tier_unsupported`; `Workflows.viewer` answers `viewer_unavailable`.
- **Who:** anyone with **edit** access to the agent can open the link (shareable with another builder; they share the one copy of the data). Readers of the agent cannot.
- **Lifetime:** 24 h by default, `--ttl` up to 168 h; `--close <id>` ends it at once (copy and recorded effects deleted). Afterwards the link shows an ended notice and routes answer `PREVIEW_ENDED`.
- Refused with `WEB_APP_PREVIEW_NEEDS_AGENT_VERSION` (exit 10) when the agent has no agent version yet: the preview runs on the live agent version — tell the user to run `lua version create` once.
- Exit codes: 2 usage (two modes, malformed id, bad `--ttl`), 3 no such app / preview, 9 auth, 10 forbidden or refused, 11 platform unavailable.
- **The plugin's use:** it is safe to run — nothing goes live and nothing is sent — so after `lua push webapp` the plugin may offer it and, when the user wants to click through, run it and hand over the link. It is in no permission list, so Claude Code asks once before it runs. Never present a preview as "deployed": only `/lua-deploy webapp` makes a version live.

Refused before upload (`WebAppBuildError`): no `index.html` in `pages.root`; built `index.html` over **256 Ki characters**; more than **1000** assets; an asset over **8 MiB**; an asset path outside `assets/[A-Za-z0-9._-/]` or over 512 chars (rename the source file); more than **200** routes.

**Opening it** (after the promote): `https://workspace.heylua.ai/apps/<agentId>/<name>` (full page in Lua Workspace) and `https://admin.heylua.ai/admin/agents/<agentId>/apps` (the admin list). `agentId` is `agent.agentId` in `lua.skill.yaml`. Anyone who can read the agent can open its apps. The browser builds only — the native desktop app does not show web apps yet.
Expand All @@ -117,6 +134,7 @@ Wall clock 30 s by default (60 s cap) → `WALL_TIMEOUT` · request body **1 MB*
| Symptom | Cause | Fix |
|---|---|---|
| `No Vite installation found for …` | `npm install` never ran in `web/` | `npm --prefix src/apps/<name>/web install --ignore-scripts` |
| A route works in `lua test webapp` but errors in a preview with `TEST_EGRESS_BLOCKED` / `test_session_tier_unsupported` / `viewer_unavailable` | previews block outside calls and refuse those runtime objects (§7a) | expected in a preview; test that path with `lua test webapp` (live) or after the deploy |
| `lua compile` fails on JSX / React types | `src/apps/*/web` missing from `tsconfig.json` `exclude` (tsconfig had comments, `apps new` skipped it) | add `"src/apps/*/web"` to `exclude` |
| `❌ No web apps found` / `No web app named …` | app not in `webApps` on the `LuaAgent` | import it in `src/index.ts`, add to `webApps` |
| `defineWebApp(<n>): route key … must look like 'GET /path'` | key typo (`'get /x'`, two spaces, no leading `/`) | `'<METHOD> /<path>'` |
Expand Down
6 changes: 3 additions & 3 deletions plugins/lua-agent-builder/mcp/lua-platform/dist/server.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions plugins/lua-agent-builder/mcp/lua-platform/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion plugins/lua-agent-builder/mcp/lua-platform/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@lua/claude-plugin-mcp",
"version": "1.12.0",
"version": "1.13.0",
"description": "Read-only MCP server for the lua-agent-builder Claude Code plugin",
"type": "module",
"main": "dist/server.js",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export async function apiRequest(path, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
'X-Lua-Client': 'claude-plugin/1.12.0',
'X-Lua-Client': 'claude-plugin/1.13.0',
},
body: body ? JSON.stringify(body) : undefined,
signal: controller.signal,
Expand Down
6 changes: 3 additions & 3 deletions plugins/lua-agent-builder/mcp/lua-platform/src/server.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import * as tools from './tools/index.mjs';
const TOOL_REGISTRY = Object.values(tools);

const server = new Server(
{ name: 'lua-platform', version: '1.12.0' },
{ name: 'lua-platform', version: '1.13.0' },
{ capabilities: { tools: {} } }
);

Expand Down Expand Up @@ -46,7 +46,7 @@ process.on('uncaughtException', (err) => {
kind: 'uncaughtException',
message: err?.message,
stack: err?.stack,
plugin_version: '1.12.0',
plugin_version: '1.13.0',
lua_cli_version: process.env.LUA_CLI_VERSION ?? null,
platform: process.platform,
ts: new Date().toISOString(),
Expand All @@ -59,7 +59,7 @@ process.on('unhandledRejection', (reason) => {
kind: 'unhandledRejection',
reason: String(reason),
stack: /** @type {any} */ (reason)?.stack,
plugin_version: '1.12.0',
plugin_version: '1.13.0',
lua_cli_version: process.env.LUA_CLI_VERSION ?? null,
platform: process.platform,
ts: new Date().toISOString(),
Expand Down
Loading
Loading