Skip to content
Deployment
Skill

/create-app

Writes, builds, and deploys an app the user asks for in the chat (they say what it should do; there is no repository and no image yet). With a filesystem and a working cpln CLI the files go into a directory on the machine and the CLI builds them; otherwise the files are stored

From plugin
ai-plugin
1031 skills2 agents2 commands1 MCP
Install
$ npx -y skills add controlplane-com/ai-plugin --skill create-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/create-app

Context preview

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

Writes, builds, and deploys an app the user asks for in the chat (they say what it should do; there is no repository and no image yet). With a filesystem and a working cpln CLI the files go into a directory on the machine and the CLI builds them; otherwise the files are stored

SKILL.md

create-app.SKILL.md
name: create-app
description: "Writes, builds, and deploys an app the user asks for in the chat (they say what it should do; there is no repository and no image yet). With a filesystem and a working cpln CLI the files go into a directory on the machine and the CLI builds them; otherwise the files are stored on Control Plane and built there. Use when the user asks to create, generate, write, vibe-code, prototype, or scaffold an app, API, site, bot, game, or service and run it on Control Plane, or to change an app that was created this way."

Create an App from the User's Request

> **Tool availability:** every MCP tool named here is on the default `core` profile (the reads also on `readonly`). The stored way needs no `cpln` CLI, git repository, Docker daemon, or file on the user's machine.

The user asks for an app that does not exist yet ("create me a todo app and deploy it"). You write its files, Control Plane builds them into an image, and the image runs as a workload with a public URL. There are two ways to get there, and choosing one is the first decision: **local** (the files go into a directory on the user's machine and the `cpln` CLI builds them) or **stored** (the files are stored on Control Plane with `mcp__cpln__write_app_files` and built with `mcp__cpln__build_image`). Everything after the build is the same either way.

Where the files go: decide by your environment

| Your environment | Which way | Where the app's files live | How the image is built | |---|---|---|---| | You can write files and run commands, and the `cpln` CLI is installed and logged in (Claude Code, Codex, Cursor, Antigravity, Amp, OpenCode, any CLI agent) | **Local** | A directory on the user's machine (`./NAME`) that you create and fill with your own file tools; it is theirs to keep, version, and edit | `cpln image build --remote --dir ./NAME --name NAME:v1 --org ORG` (builds on Control Plane, no Docker; verify flags with the `cpln` skill) | | You cannot write files or run commands (ChatGPT, Claude web, Claude desktop, any hosted chat), or you have a filesystem but no working `cpln` CLI | **Stored** | Control Plane, through `mcp__cpln__write_app_files`; they stay there between calls and sessions and the user can download them | `mcp__cpln__build_image` with no `repoUrl` |

  • **With a filesystem and a working CLI, local is the default.** The user expects the code where they can see it. Stored is fine when they ask for it, or when there is no `cpln` CLI to build with; either way, say which way you are taking.
  • **Never hand a user without a filesystem a CLI command** for an app you can store and build yourself.
  • With a filesystem but no `cpln` CLI installed or logged in, go stored; mention that installing the CLI would keep the code local next time.
  • Everything after the build (GVC and location, workload, verification, URL) is the same both ways and uses the MCP tools.

Decide the path first

| The user has | Path | Skill | |---|---|---| | A request for an app that does not exist yet (they say what it should do) | Local: files in `./NAME` → `cpln image build --remote --dir ./NAME` → `mcp__cpln__create_workload`. Stored: `mcp__cpln__write_app_files` → `mcp__cpln__build_image` → `mcp__cpln__create_workload` | this skill | | An existing container image (`nginx:latest`, `//image/api:v1`, an ECR/GCR path) | `mcp__cpln__create_workload` directly | `workload` | | A GitHub or GitLab repository URL | `mcp__cpln__build_image` with `repoUrl` → `mcp__cpln__create_workload` | `image`, `workload` | | A folder on their own machine | `cpln image build --remote --dir PATH` (CLI; this server cannot read their disk) | `image`, `cpln` | | A database, cache, queue, broker, search engine, or gateway ("I need Postgres") | `mcp__cpln__browse_templates` → `mcp__cpln__install_template` | `template-catalog` |

An app that also needs a database is both: this skill for the app, `template-catalog` for the database, then wire the connection through env and secrets. Never build a database, cache, or queue from source, and never fake an app by inlining code into a generic base image.

The journey, in order

Do every step yourself. Ask the user only where a step says to ask.

1. **Target and name.** Confirm the org (never guess it). Choose the app's name: short kebab-case, letters, digits and hyphens, at most 40 characters (`todo-app`). This one name is used everywhere: `name` for `mcp__cpln__write_app_files` and `mcp__cpln__get_app_files`, the image NAME that `mcp__cpln__build_image` produces (`//image/NAME:TAG`), and the workload name. Keep it stable for the app's whole life; a different name is a different app. 2. **Write a small, deployable app.** Bind `0.0.0.0`, listen on a fixed port taken from the `PORT` env var with a default of `8080`, and serve a `GET /healthz` that returns 200. Read configuration from env. Put no credentials, tokens, or `.env` files with values in the code (the tool refuses them); reference secrets from the workload instead (`setup-secret` skill). Write a `Dockerfile` at the root that uses `linux/amd64` base images (`node:20-slim`, `python:3.12-slim`, `golang:1.23`), installs dependencies, exposes the port, and starts the app. Auto-detection without a Dockerfile works for common stacks, but an explicit Dockerfile gives a readable log when something fails. Leave out `node_modules`, build output, and lockfiles you did not generate. **Files the user provides** (a logo, photos, a font, a PDF): a chat cannot carry their bytes, so list their paths in `uploadPaths` on `mcp__cpln__write_app_files`; the result carries an upload link for the user, and you reference the paths in the code right away (`<img src="/public/logo.png">`). A local agent that can read files may instead send small binaries inline as base64. 3. **Write the files.** Local: create `./NAME` and write the files there with your own tools; files the user provides go into that folder by hand. Stored: `mcp__cpln__write_app_files` with `org

Read more
Ships withai-plugin

Run containerized workloads across AWS, GCP, Azure, OCI, and your own hardware under one API.

Get the whole plugin

Other skills on ai-plugin.