# Moonframe > Moonframe is a factory for native desktop apps whose whole window is written in Luau. Rust and GPUI draw it, check it and keep it safe. Every panel, split, toolbar and status bar is a Luau file that reloads as you save, and its state is kept. An app runs one of two ways: as a profile of the `moonframe` binary (Luau only, no Rust build), or as a Rust binary of its own on the `moonframe` library crate. This file is for coding agents. If the user says something like "use Moonframe for my app", follow the steps below. They tell you how to pick the right way to start, which command to run, and how to check your work. ## Step 1: get the `moonframe` command Run `moonframe --help`. If the command is missing: - macOS 13 or later: `brew install moonframehq/tap/moonframe` (installs `Moonframe.app` and the `moonframe` command). - Linux or Windows: download and extract the archive for the platform from https://github.com/moonframehq/moonframe/releases. Keep the extracted folder whole: `moonframe` finds its `app/` folder (with the prebuilt providers) beside itself. Add that folder to `PATH`, or symlink the executable into one already on it. Never copy the executable on its own. Ask the user before installing anything. ## Step 2: look at the project and pick a path Check the folder the user means (usually the current one). Choose the first case that matches: 1. **A Rust crate or workspace** (there is a `Cargo.toml`): use the library (path A). If `Cargo.toml` is a workspace root with no `[package]`, ask which member crate should become the desktop app, or add a new member crate for it. 2. **A project in another language** (Python, Node, Go and so on) that needs a desktop UI: make a Luau app beside it (path B) in a subfolder such as `desktop/`. Read its data through a process provider: a program, in the project's own language if you like, that prints JSON lines. Use path A only if the user wants a Rust binary. 3. **An empty folder, or "make me a new app"**: if the app needs Rust of its own (native views, heavy computation, Rust libraries, one standalone executable), use path A. Otherwise use path B. Path B needs no Rust toolchain and is the faster start. If you can't tell which fits, ask the user. If the user wants to change Moonframe's own code too, the starter can be cloned and renamed instead (`git clone https://github.com/moonframehq/moonframe NAME`, then `mise install` and `just run`). Only do this when they ask for it. 4. **"Change Moonframe itself" or "change the app I have open"**: there is nothing to create. Edit the user's folder, `~/.config/moonframe` (or the profile's folder), following the `moonframe` skill below. Tell the user which path you picked and why before you write any files. ## Path A: a Rust app on the library ```sh moonframe init DIR --name NAME # NAME: the binary and ~/.config/NAME; DIR defaults to . ``` - **A new folder:** `init` writes a whole crate: `Cargo.toml`, `src/main.rs`, `app/main.luau`, `app/style.luau`, an example native provider (`clock`), `types/moonframe.d.luau`, and the agent skills in `.claude/skills/`. Run it with `cd DIR && cargo run`. - **An existing crate:** `init` writes only `app/`, the types and the skills, and never touches `Cargo.toml` or `src/`. It prints what to add. Make these changes yourself: - Add `moonframe = { git = "https://github.com/moonframehq/moonframe", branch = "main" }` under `[dependencies]`. - Add `[profile.dev.package."*"]` with `opt-level = 2` to the workspace root's `Cargo.toml`. Without it, GPUI and Luau are unusably slow. - Start the window from `main` with `moonframe::Moonframe::new("NAME").title("Title").app_dir(concat!(env!("CARGO_MANIFEST_DIR"), "/app")).run()`. If `main` already does something else (a CLI or a server), don't replace it. Add a second binary (`src/bin/NAME.rs`) or a new workspace member instead, and ask the user if you are unsure. With two binaries, a bare `cargo run` cannot pick one (or runs `default-run`), so name the window's: `cargo run --bin NAME`, and `cargo run -p MEMBER` for a workspace member. - The app's own Rust logic reaches the Luau UI through native providers. Implement `moonframe::Native` and register it with `.native("name", Make::default)`. For `async fn` code on tokio, implement `moonframe::AsyncNative` and register it with `.native_async("name", Make::default)` instead. Give either one a folder `app/providers/name/provider.toml` with `kind = "native"`. Luau reads its data as `app.name`. - Existing GPUI views are registered with `.view("name", View::new)` and placed from Luau with `ui.view { name = "name" }`. Use the GPUI that `moonframe::gpui_kit` re-exports: an app links only one GPUI. - `init` writes an example `clock` provider. Register it or delete `app/providers/clock/`. - The toolchain must match https://github.com/moonframehq/moonframe/blob/main/rust-toolchain.toml or be newer. - Check after each edit with `cargo run -- --check` (loads everything headlessly and reports problems). Run the app with `cargo run`, and bundle it with `cargo run --release -- bundle`. With a second binary, add `--bin NAME` (or `-p MEMBER`) to each: `cargo run --bin NAME -- --check`, `cargo run --bin NAME`, `cargo run --release --bin NAME -- bundle`. ## Path B: a Luau app run as a profile ```sh moonframe app new DIR # moonframe.toml, a shell, one mod, the skills and types, git init moonframe app link DIR # a profile that runs DIR in place; edits reload live moonframe --profile NAME # open it (NAME is [app] name in DIR/moonframe.toml) moonframe --profile NAME --check # load everything headlessly; run after each edit ``` - `app new` writes the Moonframe skills to `DIR/.claude/skills/` (moonframe, moonframe-components, moonframe-apps), the Luau API to `DIR/types/moonframe.d.luau`, and a strict `.luaurc`. Read the skills before you write UI. Your harness may only load skills from the folder it started in; if so, read the `SKILL.md` files directly. If `DIR/.claude/skills` is missing after `app new`, the installed Moonframe is older than this: read the guides linked below instead. - Lay out the window in `main.luau` and add one mod per feature under `mods/`. Use components from the catalogue before writing new ones. Restyle in `style.luau`. - For a polished composition (workspace shell, switcher, issue card, onboarding checklist), browse [Patterns](https://docs.moonframe.dev/patterns/) and read [the pattern guide](https://raw.githubusercontent.com/moonframehq/moonframe/main/docs/patterns.md). Copy only the pattern files needed into your app's components/. In a Moonframe checkout, `just patterns` opens a separate live preview/source browser. - Data comes from providers in `providers//provider.toml`. Built-ins such as `git`, `files` and `system` are already there. Use `kind = "static"` for sample JSON, and `kind = "process"` for a program that prints one JSON value per line and reads messages from stdin. A process provider runs with the user's full access, so say so in its manifest. Never pass `--yes`, which allows such providers without asking, unless the user agrees. ## Rules for any path - Luau is sandboxed: no files, network or processes. Anything that touches the machine goes through a provider. - For sandboxed computation or the `system` host capability, use a WebAssembly (WASM) provider. Read [Building WebAssembly (WASM) providers](https://raw.githubusercontent.com/moonframehq/moonframe/main/docs/wasm-providers.md) before implementing one. It covers the complete Rust component, JSON payloads, Luau integration, build and runtime checks, and source versus prebuilt distribution. Building from source needs Rust and `wasm32-wasip2`, including in a profile app. WASM has no filesystem, HTTP or process capability; use a process or native provider when those are needed. - The window reloads as you save. Run `--check` after every change and fix what it reports before you go on. - To see your result, start the window with `--background` and take a screenshot of it. - Never overwrite the user's files to make a command succeed. `moonframe init` keeps existing files, and you should do the same. ## Guides for agents (read before building UI) - [moonframe skill](https://raw.githubusercontent.com/moonframehq/moonframe/main/.claude/skills/moonframe/SKILL.md): where a feature belongs, mods, components, providers, styling, terminals, state, Inspect Element. - [moonframe-components skill](https://raw.githubusercontent.com/moonframehq/moonframe/main/.claude/skills/moonframe-components/SKILL.md): every `ui.*` element and every `use "name"` component, with props and examples. - [moonframe-apps skill](https://raw.githubusercontent.com/moonframehq/moonframe/main/.claude/skills/moonframe-apps/SKILL.md): `moonframe.toml`, profiles, `app new | link | install`, menus, bundles, turning a design into an app. - [moonframe-mockups skill](https://raw.githubusercontent.com/moonframehq/moonframe/main/.claude/skills/moonframe-mockups/SKILL.md): show the user live mockups side by side before changing anything. ## Reference - [Building WebAssembly (WASM) providers](https://raw.githubusercontent.com/moonframehq/moonframe/main/docs/wasm-providers.md): step-by-step guide for humans and agents; [website version](https://docs.moonframe.dev/wasm-providers/). - [Using the library](https://raw.githubusercontent.com/moonframehq/moonframe/main/docs/library.md): the dependency, features, `Moonframe` builder calls, native and async providers, views, layers, bundles. - [Luau API types](https://raw.githubusercontent.com/moonframehq/moonframe/main/types/moonframe.d.luau): the declarations of the whole Luau API. - [README](https://raw.githubusercontent.com/moonframehq/moonframe/main/README.md): install, quick start, working with an agent, mods from git, apps as profiles, commands. - [Example host app](https://github.com/moonframehq/moonframe/tree/main/examples/host): the crate `moonframe init` writes. - [Example apps](https://github.com/moonframehq/moonframe/tree/main/examples): 25 profile apps to copy from. ## Optional - [Releasing](https://raw.githubusercontent.com/moonframehq/moonframe/main/docs/releasing.md) - [Updates](https://raw.githubusercontent.com/moonframehq/moonframe/main/docs/updates.md) - [Provider interface (WIT)](https://raw.githubusercontent.com/moonframehq/moonframe/main/wit/provider.wit)