Start all services in a floo app locally, with credentials from your floo-provisioned managed services injected automatically.
Arguments
| Argument | Description | Default |
|---|
PATH | Project directory containing floo.app.toml | . (current directory) |
Flags
| Flag | Description | Default |
|---|
--app APP | App name or UUID (reads from config if omitted) | — |
--fixture-user EMAIL | For accounts-mode apps, start an auth proxy that injects X-Floo-User-* headers so you can test signed-in flows locally | — |
--fixture-id ID | Identity for the fixture user | dev-fixture-<email-localpart> |
--fixture-name NAME | Display name for the fixture user | the email |
--fixture-role ROLE | Role for the fixture user | member |
The --fixture-* flags only take effect for apps with access_mode = "accounts"; against any other mode floo dev warns and skips the proxy. See Add User Auth → Local development for the full walkthrough.
What happens
- Resolve — reads
floo.app.toml and collects all services with a dev_command
- Session — creates a dev session via the floo API
- Postgres auth — if the app has managed Postgres, your public IP is authorized for direct connections
- Env injection — global + per-service env vars are decrypted and injected into each service process. Managed service credentials follow the same
env.managed attachment plan as deploy; DATABASE_URL is rewritten to point to the Cloud SQL public IP when Postgres access is authorized.
- Migrations — if
migrate_command is set for a service, it runs before that service starts
- Start — each service’s
dev_command is spawned in its path directory with a colored prefix in the terminal
- Cleanup — on Ctrl+C, all child processes are terminated and the dev session is deleted
Requirements
floo.app.toml must exist in the project directory
- Every service must have
dev_command, path, and port set
- Each service must use a unique port
Example
# floo.app.toml
[app]
name = "my-app"
[services.web]
type = "web"
path = "./web"
port = 3000
dev_command = "npm run dev"
[services.api]
type = "api"
path = "./api"
port = 8000
dev_command = "uv run uvicorn app.main:app --reload --port 8000"
migrate_command = "uv run alembic upgrade head"
[services.api.env]
managed = ["postgres", "redis"]
Terminal output:
Dev session started for my-app (abc12345)
Postgres: your IP is authorized for direct connections
Redis: connection env vars injected
Service Port URL
web 3000 http://localhost:3000
api 8000 http://localhost:8000
[api] Running migrations for api...
[api] started (pid 12345)
[web] started (pid 12346)
[api] INFO Application startup complete.
[web] ready started server on 0.0.0.0:3000
Discovery vars
Each service receives env vars pointing to the other services running locally:
| Var | Example value |
|---|
<NAME>_URL | http://localhost:8000 |
VITE_<NAME>_URL | http://localhost:8000 (web services only) |
NEXT_PUBLIC_<NAME>_URL | http://localhost:8000 (web services only) |
FLOO_ALLOWED_ORIGINS | http://localhost:3000 (non-web services) |
For example, a web service in a web + api app receives API_URL=http://localhost:8000 and NEXT_PUBLIC_API_URL=http://localhost:8000.
JSON output
floo dev --json emits managed-service credentials in plaintext. The startup envelope contains the same DATABASE_URL, REDIS_URL, and any custom env vars you would see in your local process. Treat the JSON stream as sensitive: do not commit it, paste it into chat, or pipe it to a service that retains logs. If you need to share output, redact the env_vars block first.
floo dev --json 2>/dev/null
Startup emits a single JSON object:
{
"success": true,
"data": {
"session_id": "abc12345-...",
"app": "my-app",
"postgres_authorized": true,
"services": [
{
"name": "api",
"port": 8000,
"url": "http://localhost:8000",
"env_vars": {
"DATABASE_URL": "postgresql://user:pass@34.1.2.3:5432/myapp?sslmode=require",
"REDIS_URL": "redis://...",
"WEB_URL": "http://localhost:3000"
}
}
]
}
}
Log lines stream as newline-delimited JSON events:
{"event": "log", "service": "api", "stream": "stdout", "line": "Application startup complete."}
Session end:
{"event": "session_ended", "session_id": "abc12345-..."}
Errors
| Code | Meaning |
|---|
NOT_AUTHENTICATED | Run floo auth login first |
NO_CONFIG_FOUND | No floo.app.toml found. Run floo init first |
INVALID_PROJECT_CONFIG | A service is missing dev_command, path, or port, or two services share a port |
APP_NOT_FOUND | The app doesn’t exist in floo |
CANNOT_DETERMINE_IP | floo could not determine your public IP to authorize Postgres access |