Skip to content
Back to skills

Create App Yaml

ASecurity

Scan Dockerfile(s) in the current directory and generate a draft app.yaml for the gateway app store.

  • 24 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 2, 2026
ai-agentsgobashreactnextjsnodedockergitapibackend

Works with

  • api
  • mcp

Security analysis

A100/100

Scanned September 2, 2026

npx -y skills add 0xMaxMa/claude-gateway --skill create-app-yaml --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Create App Yaml?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Create App Yaml
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/0xmaxma-create-app-yaml/badge)](https://www.skillsdirectory.com/skills/0xmaxma-create-app-yaml)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: create-app-yaml
description: Scan Dockerfile(s) in the current directory and generate a draft app.yaml for the gateway app store.
user-invocable: true
allowed-tools:
  - Read
  - Write
  - Bash(ls *)
  - Bash(find * -name Dockerfile*)
---

# /create-app-yaml — Generate Draft app.yaml

Arguments passed: `$ARGUMENTS`

Reads Dockerfile(s) in the current working directory and generates a draft `app.yaml`.

---

## Step 1 — Discover Dockerfiles

```bash
find . -name "Dockerfile*" -not -path "*/node_modules/*" -not -path "*/.git/*"
```

List what you found. If none, tell the user and stop.

---

## Step 2 — Infer services

For each Dockerfile, infer:
- **Service name** from the directory name or `Dockerfile.<name>` suffix
- **Exposed ports** from `EXPOSE` instructions — pick the first as the main port
- **Environment variables** from `ENV` instructions — these become `env:` entries
- Whether it looks like a web app (serves HTML/static files) vs an API

---

## Step 3 — Generate app.yaml

Write a draft `app.yaml` to the current directory:

```yaml
apiVersion: apps.getpod.ai/v1
name: <inferred-from-dirname>      # lowercase, hyphens only
version: 1.0.0
commit: ""                          # fill in the 40-char commit hash before release

services:
  <service-name>:
    build: .                        # or ./subdir if not root
    ports:
      - name: <api|web>
        container: <port>           # port the app listens on inside the container
        host: <port>                # REQUIRED — host port to expose (default: same as container)
        type: <api|web>             # api = REST/backend, web = serves HTML
        rate_limit: 60              # requests per second
    environment:
      # Secrets (no default value) — users will be prompted at install time
      - MY_SECRET_KEY
      # Variables with defaults
      - LOG_LEVEL=info
    healthcheck:
      test: wget -qO- http://localhost:<port>/health || exit 1
      interval: 30s
      timeout: 10s
      retries: 3
```

Rules for `host` (required on every port):
- `host` is the port exposed on the machine; `container` is the port the app listens on inside the container. Every declared port **must** have an integer `host` — the gateway rejects a manifest without it (`ports["<name>"].host is required and must be an integer`), so a host-less app fails to install.
- Default `host` to the same value as `container` unless that port is already taken.
- `host` must be `>= 1024`, must not be a banned port (`22`, `80`, `443`, `10850`), and must be unique across the app's ports. The user can override it at install time, but the field must be present.

Rules for port type:
- `type: web` if Dockerfile serves static HTML, runs Next.js/React/Vite, or uses nginx/caddy
- `type: api` otherwise

Rules for environment variables:
- If the Dockerfile has `ENV FOO=bar` → `FOO=bar` (has default)
- If you see `ARG FOO` or `ENV FOO` with no value → `FOO` (secret, no default — installer prompts for it)
- If the value has a **sensible default the operator should still be able to override** (e.g. `NEXTAUTH_URL`, a public base URL, a tunable timeout) → `FOO=!default:<value>`. It is prompted like a bare key (visible and editable in the install UI, pre-filled with `<value>`), but if the operator leaves it blank the default is written to `.env` — so the app never boots with an empty required field.
  - The value is taken verbatim and may contain `:` and `/` — e.g. `NEXTAUTH_URL=!default:http://localhost:3737`.
  - Prefer this over a bare `FOO` whenever a good default exists, and over a static `FOO=value` whenever the operator should be able to change it at install.
- If the value is a **per-install random string** the user cannot meaningfully supply (session secret, DB password, internal API token) → `FOO=!generate:<encoding>:<bytes>`. The installer fills it with a fresh random value automatically, so the install never stalls asking for it.
  - Encodings: `hex`, `base64`, `base64url` (use `base64url` when the value is embedded in a URL or connection string — it has no `+` `/` `=`). Length is `8`–`512` bytes.
  - Examples: `NEXTAUTH_SECRET=!generate:base64:32`, `DB_PASSWORD=!generate:base64url:24`
  - Only leave a bare `FOO` (no `=`) for values a **human** must answer (a public URL, an external account, an API key from a third party).

---

## Step 4 — Show and explain

Show the generated `app.yaml` to the user and explain:
1. They must fill in `commit:` with a 40-char hex commit hash before publishing
2. They can add a `healthcheck:` if the service has a health endpoint
3. If the app has an agent, they can add an `agent:` service block
4. The `rate_limit` is requests per second — adjust to match expected load
5. **Validate before publishing** — run `POST /api/v1/apps/inspect` with `local_path` (or the `inspect_app` MCP tool) pointed at the app directory. This runs the same manifest validation as install without needing a pinned commit, so a missing `host` or other schema error is caught locally instead of failing the install wizard after publish.

---

## Notes

- Never write `network_mode`, `privileged`, or `cap_add` — these are blocked by the gateway
- Do not use floating `:latest` image tags — warn the user to pin versions
- The `commit:` field is intentionally left empty as a placeholder

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.