Paste in the browser or deploy from Cursor or Claude Code. Same app, two doors. Self-hosted with Docker.
The aha in one beat: you write one Python function with type hints. floom gives one live app: a generated form, a REST surface, a share link, and MCP tools that call the same actions. No duplicate logic between browser and IDE.
Who uses what: Cursor and Claude Code (and similar) integrate via MCP (deploy, run, secrets). Functionality is agent- and API-first: behavior lives in the control plane and is exposed through REST, MCP, and CLI. The web UI is a thin wrapper on that same API: paste a script, use generated forms, run, and share. OpenAPI is generated from your Python; you do not hand-author it for Floom apps.
You write this:
from floom import app
@app.action
def generate_invoice(client: str, amount: float, due_date: str):
pdf = create_pdf(client, amount)
return {"url": pdf.url}floom gives you:
- A web form with fields for client, amount, and due_date (auto-generated from type hints)
- A REST API at
/api/generate_invoicewith OpenAPI spec - A shareable link anyone can use
- Docker sandboxing so each run is isolated
No Dockerfile. No frontend code. No deploy config.
docker run -p 3000:3000 -p 3001:3001 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /tmp/floom-workspaces:/tmp/floom-workspaces \
-v /tmp/floom-storage:/tmp/floom-storage \
-v floom-data:/data \
ghcr.io/floomhq/floomOpen localhost:3000. Paste a Python function. Hit "Go Live."
| Python type | Generated UI |
|---|---|
str |
Text input |
int |
Number input |
float |
Number input (decimal) |
bool |
Checkbox |
Literal["a","b"] |
Dropdown select |
dict |
JSON editor |
| Default values | Pre-filled placeholders |
Your app can remember things across runs. No database setup.
from floom import app, remember
@app.action
def count_visits(name: str) -> dict:
visits = (remember("visits") or 0) + 1
remember("visits", visits)
return {"message": f"Hello {name}! Visit #{visits}"}Got code from ChatGPT with no functions or type hints? floom can handle it.
import requests
city = "Berlin"
response = requests.get(f"https://wttr.in/{city}?format=j1")
data = response.json()
print(f"Temperature in {city}: {data['current_condition'][0]['temp_C']}°C")With FLOOM_AI_ENHANCE_INGEST=1 and GEMINI_API_KEY set, floom can use Google Gemini after mechanical extraction to detect city as a form input, identify requests as a dependency, and wrap the script in a callable function. By default ingest is mechanical only. Get a free key.
| Example | What it does |
|---|---|
| Invoice Generator | Create invoices with automatic tax calculation |
| Text Analyzer | Count words, find common phrases, detect sentiment |
| Unit Converter | Convert temperatures and distances between units |
| Visit Counter | Greet visitors and track counts with remember() |
floom is built for AI-assisted workflows. Every app gets an OpenAPI spec, and the MCP server gives agents direct access.
One command adds floom to your MCP config:
npx @floomhq/cli setup-mcpOr add manually to your MCP config:
{
"mcpServers": {
"floom": {
"command": "npx",
"args": ["-y", "@floomhq/mcp-server"],
"env": { "FLOOM_URL": "http://localhost:3001" }
}
}
}npm install -g @floomhq/cli
floom deploy app.py --name "My App"
floom run greet name=world
floom doctor # verify setup- Deploy with HTTP calls: set
config: { network: true }in deploy, orRUNNER_NETWORK=bridgeon the server - Deploy with secrets: use the
manage_secretstool (persistent), or passsecretsinrun(one-time) - Discover actions:
curl http://localhost:3001/v1/apps/my-app - Call directly:
curl -X POST http://localhost:3001/v1/apps/my-app/greet -H 'Content-Type: application/json' -d '{"name": "world"}'
The Quick Start command above runs the all-in-one container. Encryption key is auto-generated and persisted in the floom-data volume.
git clone https://github.com/floomhq/floom
cd floom
npm run setup:local # generates encryption key + .env
npm install
docker-compose up --build- Web UI:
http://localhost:3000 - API:
http://localhost:3001 - Health:
http://localhost:3001/health
Environment variables
| Variable | Required | Default | Description |
|---|---|---|---|
MASTER_ENCRYPTION_KEY |
No | Auto-generated | 32-byte base64 key for secrets encryption |
COMPUTE_BACKEND |
No | docker |
docker for self-hosted |
PORT |
No | 3001 |
Server port |
API_KEY |
No | Bearer token to protect API | |
RUNNER_IMAGE |
No | floom-runner:latest |
Docker image for code execution |
RUNNER_MEMORY |
No | 512m |
Memory limit per container |
RUNNER_CPUS |
No | 1 |
CPU limit per container |
RUNNER_NETWORK |
No | none |
Network mode (none for isolation) |
FLOOM_AI_ENHANCE_INGEST |
No | (off) | Set to 1 or true to opt in to Gemini post-extract ingest |
GEMINI_API_KEY |
No | Required only if FLOOM_AI_ENHANCE_INGEST is enabled |
See .env.example for the full list.
npm install -g @floomhq/cli
floom deploy my-app.py --name "My App"
floom run greet name=world
floom list
floom logs
floom doctor
floom storage list
floom share create <endpoint_id>
floom setup-mcpPython function (type hints)
|
OpenAPI schema extraction
|
+----+----+
| |
Web form REST API
| |
Docker sandbox (isolated execution)
|
SQLite (state + storage)
floom/
├── apps/web/ # Next.js frontend
├── packages/
│ ├── cli/ # CLI tool
│ ├── client/ # TypeScript API client
│ ├── mcp-server/ # MCP tools for AI agents
│ ├── openapi-form/ # Form generation from OpenAPI
│ ├── shared/ # Shared types
│ └── ui/ # Shared React components
└── services/
├── control-plane/ # Hono.js API server
└── runner/ # Python execution runtime + SDK
npm install
npm run build # Build all packages
npm test # Run all tests- Single instance only: The control plane uses in-memory state for run progress and deploy tracking. Running multiple control plane instances will cause state to be lost between them. A Redis-backed implementation is planned for multi-instance deployments.
- Artifact serving: Artifacts larger than 1MB are not served inline. S3-backed artifact storage is planned for production use.
See CONTRIBUTING.md.
MIT. See LICENSE.