> ## Documentation Index
> Fetch the complete documentation index at: https://docs.heylua.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# lua apps

> Scaffold a web app on the agent and run it locally with hot reload, its routes running in the sandbox as you

`lua apps` creates and runs [web apps](/concepts/apps): pages and typed routes that belong to the agent. `new` writes a new app into the project; `dev` runs one on your machine. Neither pushes anything. Use [`lua test webapp`](/reference/cli/test) to call one route and [`lua push webapp`](/reference/cli/push) to create a version.

*Requires lua-cli 3.42.0 or later.*

## Synopsis

```bash theme={null}
lua apps new <name>
lua apps dev <name> [--port <port>]
```

## Description

### lua apps new

`lua apps new <name>` runs in the root of an agent project, where `lua.skill.yaml` is. It writes `src/apps/<name>/`:

| File | Contents |
| - | - |
| `app.ts` | `defineWebApp` with the name, a nav entry, and one route, `GET /hello`, that greets the signed-in person |
| `web/` | A Vite + React project with `@lua-ai-global/ui` and Tailwind v4: `index.html`, `package.json`, `tsconfig.json`, `vite.config.ts`, and `src/` with `main.tsx`, `App.tsx`, and `index.css` |

It then edits two project files:

* `src/index.ts`: imports the app and adds it to `webApps` on your `new LuaAgent({...})`, creating the property when it is missing. When it cannot find the agent, or `webApps` is not an array, it leaves the file as it is and prints the two lines to add.
* `tsconfig.json`: adds `src/apps/*/web` to `exclude`, so the agent's TypeScript build never loads the page project. When the file is not plain JSON (it has comments or trailing commas), it prints the line to add instead.

The name must be lower-case letters, digits, and dashes, starting with a letter. The command never overwrites anything: when `src/apps/<name>` exists it stops. Run `npm install` in `web/` afterwards; the command prints the next steps.

<Note>
  lua-cli 3.42 to 3.45 also write the page client into `web/src/lua/client.ts`. To use the `@lua-ai-global/app-client` package instead, run `npm install @lua-ai-global/app-client` in `web/`, change `from './lua/client'` to `from '@lua-ai-global/app-client'` in `web/src/main.tsx` and `web/src/App.tsx`, and delete `web/src/lua/client.ts`.
</Note>

### lua apps dev

`lua apps dev <name>` compiles the project and runs the app locally:

* The pages are served by the app's own Vite (the one installed in `web/`), with hot reload. The command prints the URL.
* Every route call from the page runs in the sandbox on your machine, as you. `Data` and `env()` are the live ones, as for [`lua test`](/reference/cli/test), so writes are real. The project's `.env` is loaded once for the whole session.
* Route files are watched. A change recompiles the routes, and the next call runs the new code. When the recompile fails, the previous routes keep serving and the error is printed.

There is no handoff from a shell locally: the page runs as you without signing in. Ctrl+C stops the server.

## Arguments

| Argument | Description |
| - | - |
| `name` | The app's name: lower-case letters, digits, and dashes, starting with a letter. For `dev`, an app listed under `webApps` on the agent |

## Options

| Option | Applies to | Description | Default |
| - | - | - | - |
| `--port <port>` | `dev` | Port for the dev server | Vite's default |

## Examples

Scaffold an app and install its page project:

```bash theme={null}
lua apps new ops-dashboard
cd src/apps/ops-dashboard/web && npm install
```

```text Output theme={null}
  created src/apps/ops-dashboard/app.ts
  created src/apps/ops-dashboard/web/index.html
  created src/apps/ops-dashboard/web/package.json
…
  updated src/index.ts                     webApps: [opsDashboard]
  updated tsconfig.json                    exclude: "src/apps/*/web"

✅ Web app ops-dashboard created
✨ Next:
   Install pages:  `cd src/apps/ops-dashboard/web && npm install`
   Run locally:    `lua apps dev ops-dashboard`
   Ship:           `lua push webapp --name ops-dashboard`
```

Run it on a fixed port:

```bash theme={null}
lua apps dev ops-dashboard --port 5180
```

Call one route, then push a version:

```bash theme={null}
lua test webapp --name ops-dashboard --route 'GET /hello'
lua push webapp --name ops-dashboard --force
```

## Exit codes

| Code | When |
| - | - |
| `0` | `new`: the app was written. `dev`: stopped with Ctrl+C |
| `1` | `dev`: the compile failed, or no Vite is installed in `web/` (run `npm install` there) |
| `2` | `new`: the name is invalid, `src/apps/<name>` exists, or there is no `lua.skill.yaml`. `dev`: no app with that name in the compiled agent |
| `9` | `dev`: no credential, or the platform refused it |

## See also

* [Build and open your first web app](/build/apps/quickstart)
* [Write routes and pages](/build/apps/routes-and-pages)
* [`lua test webapp`](/reference/cli/test) and [`lua push webapp`](/reference/cli/push)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.