Skip to content
LACE
  • v0.1 Current
  • Python
  • TypeScript Soon

lace-app-sdk

Clone the repo & run locally

Graduated apps are real git repos. Clone them, run them locally against an emulator, and push them back through the same release pipeline.

Clone

terminalbash
lace-app clone acme.field_intake
cd field_intake
ls -la
# app/  lace_app_manifest.json  LaceApp.yaml  compose.yaml  ui/  tests/
  • lace-app clone <app> [--dir DIR] — mints a short-lived git credential via GET /v1/apps/{app_id}/git-credential and clones with an ephemeral helper.
  • Never stores a raw GitHub token — the helper is scoped to the single git clone invocation.
  • If credential minting fails, it degrades to a plain git clone so advanced git setups still work.

Run locally — lace-app dev

terminalbash
lace-app dev --port 8080
# → boots compose.yaml (postgres/minio/nats/redis + api)
# → mounts app/ into the runtime emulator, runs migrations, mounts routes at /apps/<app_id>/api/*
curl http://localhost:8080/apps/acme.field_intake/api/notes | jq

lace-app dev is the local emulator (APB-020). It:

  1. Reads compose.yaml (copied from src/lace_app_sdk/templates/lace_compose.yaml) and boots Postgres, MinIO/S3, NATS, and Redis.
  2. Creates a local .lace/ state dir: dev credentials pointer, lace_app_manifest.json cache, build artifacts, and a launcher at .lace/_dev_app.py.
  3. Runs migrations via the app's migration_provider (if declared), registers collections through AppDataService, and mounts route/agent providers at /apps/<app_id>/api/*.
  4. Watches app/ for changes (reload).

Flags: --port PORT, --dir DIR. Requires the runtime extra for migration-apply: pip install lace-app-sdk[runtime]. Without it, dev still boots but warns about skipped migrations.

What the repo looks like on disk

field_intake/
├── app/
│   ├── __init__.py
│   ├── data.py          # AppDataCollectionSchema (typed collections)
│   ├── tools.py         # @tool handlers + AppToolDescriptor
│   ├── agents.py        # AgentDefinition + AppAgentProvider
│   ├── routes.py        # AppRouteProvider (FastAPI routes)
│   └── migrations.py    # AppDataMigrations
├── ui/                  # federated runtime-UI (if declared)
├── lace_app_manifest.json  # canonical manifest (what you publish)
├── LaceApp.yaml         # sidecar / deploy descriptor
├── compose.yaml         # local dev stack (from templates/lace_compose.yaml)
├── .lace/               # local state: credentials, dev AppState, build cache
└── tests/               # proof-lane fixtures

The local stack

compose.yaml is a slimmed version of the platform's own compose. You can docker compose up it directly, but lace-app dev wraps that plus the emulator bootstrap so routes and agents resolve the same way they do in the sidecar.

ServiceWhy it runs locally
postgresAppDataService collections + platform stores
minioBlob store for put_blob / get_blob + UI bundles
natsEvent bus for dataset/KG events
redisCache + distributed locks
api + frontendOnly if you run the full platform; lace-app dev is lighter — just the app sidecar

Inner-loop workflow

  1. Edit app/data.py, app/tools.py, app/agents.py, or app/routes.py.
  2. Hit GET /apps/<app_id>/api/notes locally or use the federated UI at /apps/<app_id>/.
  3. Run proof lanes: lace-app test (see testing).
  4. Push: lace-app push (polls CI releases) or lace-app deploy --cloud (direct seal/upload/activate, AFV-016).

Troubleshooting

  • lace-app dev warns about missing runtime — install pip install lace-app-sdk[runtime] inside the repo or in the sidecar.
  • Port in uselace-app dev --port 8081.
  • State bleed between apps — each app gets its own .lace/; wipe it with rm -rf .lace to re-bootstrap.

Next: what gets installed or jump to the SDK itself.