Skip to content

Run Loom on your laptop

just local-up stands up a browsable, authenticated Loom on a laptop, with no AWS account. Floci, a local AWS emulator, provides the managed pieces (RDS, Cognito, S3, ECR); the app tier (frontend, backend, and a reverse proxy standing in for the ALB) runs from a chant-generated docker-compose.yml, wired to Floci. You get the full web app. Real Postgres, real API, logged in as an admin local-dev user. Agents now deploy locally too — the Floci image emulates Bedrock AgentCore’s control plane — though invoking one returns a canned stub, not real agent reasoning (see below).

  • Docker, the only requirement. No AWS account, no cloud calls.
  • This repo, npm install.
just local-up

That runs, in order: Floci up, vendor Loom v1.6.0, synth and provision the infrastructure on Floci, build the app images, resolve the Floci values into a .env, generate the compose and nginx config, and docker compose up. When it finishes:

open http://localhost:8080

You land in the Loom UI as local-dev (admin, all scopes), with no login step. Browse the catalog, settings, memories, credentials, costs; everything the API serves from Postgres is live.

just local-down # tear down the app stack and Floci
LayerLocal status
PostgreSQL (data tier)Real — a genuine Postgres 15; the backend runs its real schema migrations against it
Backend API (FastAPI)Real — all DB/config routers: catalog, settings, costs, memories, security, registry, mcp, identity, credentials, approvals, logs, traces
Frontend (SPA)Real — served through the proxy at one origin
S3 / ECR / KMS / ECSReal — bucket, image registry, cluster all provisioned by chant on Floci
Auth / loginDev shortcut — Loom’s built-in bypass (see below), not a real login
The “ALB”Proxy stand-in — path routing only (/api/* and /health to the backend, everything else to the frontend); no TLS or WAF
Agents (deploy)Real — the Floci image emulates AgentCore’s control plane (runtimes, endpoints, gateways, memory, workload identity)
Agents (invoke)Stub — invoke-agent-runtime returns a canned response, not real agent reasoning
IAM enforcement, KMS crypto, CloudWatch/OTelNot real — see Local caveats

Floci’s Cognito can’t mint validatable JWTs. It returns opaque tokens, and the Cognito validator fetches its JWKS from real AWS for a pool that only exists in Floci. So the local tier leaves LOOM_COGNITO_USER_POOL_ID unset, which engages Loom’s own dev bypass (backend/app/dependencies/auth.py): with no Cognito pool and no external IdP, every request is a local-dev user with the admin groups and all scopes. This is Loom’s sanctioned local-dev path. It exercises the real auth code and short-circuits only the identity check. Production uses the real Cognito pool and real JWT validation.

The AgentCore-enabled Floci image (ghcr.io/lex00/floci:agentcore, loomster#98) emulates Bedrock AgentCore’s control plane with full state — the resources chant synthesizes (Runtime, RuntimeEndpoint, Memory, Gateway, WorkloadIdentity) actually deploy and are queryable, so the loom-agents wave reaches a real CREATE_COMPLETE on Floci — the resources exist and respond, they aren’t CloudFormation bookkeeping.

What’s still a stand-in is the data plane: invoke-agent-runtime returns a canned response ({"output":"yes"} by default, tunable via FLOCI_SERVICES_BEDROCK_AGENT_CORE_INVOKE_RESPONSE), not a real agent run. The app stays fully usable — the agents catalog lists and manages definitions from Postgres, and deploys resolve — but an invoked agent replies with the stub rather than genuine reasoning. For real agent execution, deploy the production / production-ha tier against real AWS.

Nothing here is hand-authored config. The compose file is generated by chant from a docker-lexicon graph (chant build src/local --lexicon docker), the nginx routing is generated from Loom’s real ALB rules, and Floci is provisioned by chant. The harness (scripts/local/local-up.sh) is thin glue that resolves the runtime values and calls chant and docker compose.

Before you rely on anything you see locally, read Local caveats. The local run diverges from real AWS in specific, load-bearing ways.