Skip to content
Automation
Skill

/raw-app

MUST use when creating raw apps.

From plugin
windmill
17k40 skills2 agents3 MCP
Install
$ npx -y skills add windmill-labs/windmill --skill raw-app --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/raw-app

Context preview

The summary Claude sees to decide when to auto-load this skill.

MUST use when creating raw apps.

SKILL.md

raw-app.SKILL.md
name: raw-app
description: MUST use when creating raw apps.

Windmill Raw Apps — CLI workflow

This guide covers raw apps from the terminal: scaffolding via `wmill app new`, the on-disk layout, and the file-based conventions the CLI uses to represent backend runnables and data table configuration. The platform shape (how a raw app behaves at runtime — frontend bundling, runnable types, datatable SDK calls) is covered in the companion authoring guide.

Creating a Raw App

**You — the AI agent — create the app yourself by running `wmill app new` with the right flags. Do NOT tell the user to "run `wmill app new` and follow the prompts" or wait for them to do it.** The bare `wmill app new` is an interactive wizard that hangs waiting for stdin in any non-TTY context (which includes you). Always pass flags.

Step 1 — Gather the three required values by asking the user

You need three things to run the command:

1. **summary** — a short description of the app 2. **path** — the windmill path, e.g. `f/folder/my_app` or `u/username/my_app` 3. **framework** — one of `react19` (recommended), `react18`, `svelte5`, `vue`

If the user's request did not supply *every* one of these explicitly, ask. Do not guess values, do not invent paths, do not pick a framework on the user's behalf, do not "just use react19 because it's the default".

Use whichever interactive question facility your runtime provides — a structured multi-choice tool if available, otherwise plain chat — and group all missing fields into a single round-trip so the user answers them at once:

  • For `framework` — multiple-choice with the four allowed values; mark `react19` as `(Recommended)` and put it first.
  • For `summary` and `path` — provide one or two example values as multiple-choice options (the user can pick "Other" to type a free-form answer).

Only proceed once you have concrete values for all three. If the user replies with something ambiguous, ask again rather than guessing.

Step 2 — Run the command yourself

Once you have summary + path + framework, run it:

wmill app new \
  --summary "Customer dashboard" \
  --path f/sales/dashboard \
  --framework react19

That's the minimum. The datatable wizard and the "Open in Claude Desktop?" prompt are skipped silently because passing any of `--summary`/`--path`/`--framework` puts the command in non-interactive mode.

Optional flags

Layer these in only when the user asked for them:

| Flag | When to add it | |---|---| | `--datatable <name>` | The user wants this app wired to a specific Windmill datatable. Without it, the app is created with no datatable. | | `--schema <name>` | Together with `--datatable`. Creates the schema with `CREATE SCHEMA IF NOT EXISTS` if it doesn't already exist. | | `--overwrite` | The target directory already exists and the user said it's OK to replace. Without it, non-interactive mode aborts with an error so you don't clobber existing work. | | `--no-open-in-desktop` | Already implied in non-interactive mode; only needed if you're somehow running interactively. |

Step 3 — Offer the visual preview

After `wmill app new` and any initial edits to `App.tsx` / `index.tsx`, **offer** to open the visual preview as a one-sentence next step (e.g. "Want me to open the visual preview?"). Don't auto-open — opening the dev page has side effects (browser window, possibly a `launch.json` entry when an embedded preview tool is in play) the user should consent to.

For apps the preview command runs from the app folder (`cd <app_path>__raw_app && wmill app dev …`); the `preview` skill picks the proxy vs direct branch based on whether the runtime exposes a tool that can embed a localhost URL. If the user already asked to see/preview/visualize the app in their original request, skip the offer and just invoke the skill.

Anti-patterns to avoid

  • ❌ Running `wmill app new` with no flags (the prompt will hang).
  • ❌ Telling the user to "run `wmill app new` and follow the prompts" — that's a step backwards from what you can do directly.
  • ❌ Inventing a path/summary/framework instead of asking the user.
  • ❌ Defaulting to `react19` because the user didn't say — even sensible defaults must be confirmed.
  • ❌ Passing `--overwrite` automatically when the directory exists — confirm with the user first.

Interactive (only when a human is at the terminal)

wmill app new

This is the wizard. It only works when run by a human in a real terminal. Don't call it this way from an agent.

On-disk app layout

my_app__raw_app/
├── AGENTS.md              # AI agent instructions (auto-generated)
├── DATATABLES.md          # Database schemas (run 'wmill app generate-agents' to refresh)
├── raw_app.yaml           # App configuration (summary, path, data settings)
├── index.tsx              # Frontend entry point
├── App.tsx                # Main React/Svelte/Vue component
├── index.css              # Styles
├── package.json           # Frontend dependencies
├── wmill.ts               # Auto-generated backend type definitions (DO NOT EDIT)
├── backend/               # Backend runnables (server-side scripts)
│   ├── <id>.<ext>         # Code file (e.g., get_user.ts)
│   ├── <id>.yaml          # Optional: config for fields, or to reference existing scripts
│   └── <id>.lock          # Lock file (run 'wmill generate-metadata' to create/update)
└── sql_to_apply/          # SQL migrations (dev only, not synced)
    └── *.sql              # SQL files to apply via dev server

Backend runnables on disk

Add a code file to the `backend/` folder:

backend/<id>.<ext>

The runnable ID is the filename without extension. For example, `get_user.ts` creates a runnable with ID `get_user`.

Supported languages (extension-driven)

| Language | Extension | Example | |------------------|--------------|------------------| | TypeScript | `.ts` | `myFunc.ts` | | TypeScript (Bun) | `.bun.ts` | `myFunc.

Read more
Ships withwindmill

Windmill is fully open-sourced (AGPLv3) and Windmill Labs offers dedicated instances and commercial support and licenses.

Get the whole plugin