# Python app recipe

URL: https://briq.cloud/cookbook/python

> Your Python code running as a service, from files or a GitHub repo: it installs requirements.txt and starts it. No image to build.

Tags: app, language

Guides:

- [Run your own app](https://briq.cloud/docs/guides/run-your-own-app.md): Your code as a running service, with a URL, in one call and no image to build.
- [Run a GitHub repo](https://briq.cloud/docs/guides/run-a-github-repo.md): An app from a repo, running with a URL. The briq downloads the code itself, and nothing is built on your side.

## Run it

MCP:

```ts
briq_run({
  recipe: "python",
  params: {
    "version": "3.12",
    "packages": [],
    "port": 8080,
    "env": {},
    "size": "small"
  },
  wait: true
})
```

REST:

```bash
curl -X POST https://api.briq.cloud/v1/briqs \
  -H "Authorization: Bearer $BRIQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "recipe": "python",
    "params": {
      "version": "3.12",
      "packages": [],
      "port": 8080,
      "env": {},
      "size": "small"
    },
    "wait": true
  }'
# → { "briqs": [{ "id": "bq_…", … }], "outputs": { "APP_URL": "…" }, … }

# ... when done, for each briq id
curl -X DELETE https://api.briq.cloud/v1/briqs/<id> \
  -H "Authorization: Bearer $BRIQ_API_KEY"
```

## Parameters

| Name | Type | Options | Default | What it does |
| --- | --- | --- | --- | --- |
| `version` | enum | 3.12, 3.13, 3.14 | "3.12" | — |
| `files` | record | { "path": "content" \| { base64 } } | — | Your app's files, path → content (text, or { base64 }). Relative paths go under /app. For a bigger app, or one already on GitHub, pass `repo` instead. Without either, a hello-world app. |
| `repo` | object | { url, ref?, dir?, token? } | — | Your code from a repo instead of `files`. url: "github.com/owner/app", or on another host (GitLab, Bitbucket, Codeberg) the https URL of a .tar.gz archive, without ref. ref: a branch, tag or commit sha; default branch; a full sha pins the code. dir: the app's folder, e.g. "backend". token, private repos only: { secret: "GITHUB_TOKEN", value }, a fine-grained token with Contents: read on this repo; never the person's own token. The briq downloads the code itself, installs when a lockfile changed, runs `build` when the commit changed, then `start` |
| `packages` | string[] | — | [] | Extra packages to install at each start, besides your manifest |
| `install` | string | — | — | Shell command replacing the default install step: run before each start; with `repo`, only when a lockfile changed (go and rust build here, at each start) |
| `build` | string | — | — | Shell command run after the install, e.g. "npm run build": with `repo`, only when the commit or the install changed; with files, at each start |
| `start` | string | — | — | Shell command that starts the app (it must not exit). With `repo`, pass it: the default (python app.py, ruby app.rb…) rarely matches a repo; node runs npm start, bun bun run start |
| `port` | number | — | 8080 | — |
| `env` | record | { NAME: "value" \| { secret, value? } } | {} | Env vars. A credential goes as { secret: "NAME", value: "…" }: stored encrypted and never shown again |
| `size` | enum | nano, small, medium, large | "small" | A build (Next.js, Nuxt, a Rust release, a Go toolchain) is many times faster on medium or large: small has one shared CPU, slowed down once a long build used its burst. Up to small, a sleeping briq wakes from a memory snapshot in seconds; medium and large start from scratch on a wake (with `repo`: the branch is looked up again, and a new commit is installed and built before the app answers) |
| `diskGb` | number | — | — | With `repo` only: the size in GB of the volume (/work) that holds the code, its dependencies and build caches |

## Outputs

Returned by `briq_run` once the stack is healthy. Hosts resolve inside your team network; secrets are generated per run.

| Output | Value |
| --- | --- |
| `APP_URL` | `http://app.<stack>.internal:8080` |

## What it runs

| Briq | Image | Ports | Size | Volume |
| --- | --- | --- | --- | --- |
| app | `python:3.12-slim` | 8080 | small | — |

## When to use it

* You wrote a small Flask, FastAPI or plain `http.server` app and want it running next to its
  database, with a URL, without building an image.
* A script should run as a service: a webhook receiver, a scheduler, a bot.

## Tips

* **Code in a repo**: pass `repo: { url: "github.com/owner/app" }` instead of `files`. See
  [Run a GitHub repo](https://briq.cloud/docs/guides/run-a-github-repo).
* **A bot or a scheduler** that only makes outgoing calls is not seen as use, so it sleeps after
  its `sleep` window. Give it `sleep: "never"` (always on, Pro plan and above), or a window longer
  than the gap between its runs.
* **Pass the code as `files`**: `{ "app.py": "…", "requirements.txt": "flask\npsycopg[binary]" }`.
  Relative paths go under `/app`, the working directory. They are written before the app starts,
  and again whenever it starts over.
* **`requirements.txt` is installed at each start**; `packages: ["flask"]` adds more without a
  file. The packages stay on the briq's disk, so after the first start the install is quick.
* **`start`** is the command when it is not `python app.py`, e.g.
  `"uvicorn main:app --host :: --port 8080"`.
* **Listen on `::` and on `$PORT`** (8080 by default): the private network is IPv6.
* **Wire a database** with `env`: run the [postgres](https://briq.cloud/cookbook/postgres) recipe in the same stack
  first and pass its `DATABASE_URL` as a secret, `{ secret: "DATABASE_URL", value: "…" }`.
* **Publish it as you run it**:
  `briq_run({ recipe: "python", params: { files }, expose: "private" })` returns `URL` (`"public"`
  instead of `"private"` for anyone).
* **If it exits before it answers**, the run fails and the briq is in `error`; `briq_logs` shows
  the traceback. `briq_destroy` it, fix the files, and run again. If it exits later, the briq
  stops with the code in `lastExit`.
* **Step by step**: [Run your own app](https://briq.cloud/docs/guides/run-your-own-app), with a database and a URL.
