Skip to content

The Lightspeed manual

Local development

The development launcher runs Lightspeed from your checkout. PostgreSQL, object storage, and Temporal run in Docker; Rust and TypeScript processes run on your machine. This keeps the durable services available while you edit, rebuild, and restart the code that uses them.

If you want to try the product before changing it, follow the quickstart’s source setup. This page picks up from that setup and explains how to choose an edit loop, find the code that owns a behavior, and keep local state useful while developing.

Prepare the checkout

Run the commands below from the repository root. The complete local product needs Rust and Cargo through rustup, Node.js 24.21.0 or newer with npm, and a running Docker daemon with Docker Compose v2. The checked-in Rust toolchain selects the compiler. Rust dependencies also need a native build toolchain and protoc, including its standard .proto include files.

Start the product with:

Terminal window
./dev.sh

The launcher installs npm workspace dependencies when they are missing or the root lockfile has changed. It starts the infrastructure, applies the Rust database migrations, and starts the application processes. Platform applies its own database migrations during startup. Wait for the readiness checks, then open http://localhost:5173/app/.

A root .env is loaded automatically if present. You can start without a model API key and add a universe credential through Models → Add provider. A provider-backed run still needs a valid credential for its selected model. The quickstart covers that first connection and the development account.

Plain ./dev.sh also starts lightspeed-envd on the host. It runs commands as your OS user, with a working directory under .lightspeed-dev/envd/workspace; that directory is not a sandbox. Sessions must still have an environment configured before using it. Pass --no-envd when your work doesn’t need a machine, or follow the local attachment walkthrough to configure it.

Development logins

The default authenticated ./dev.sh (full profile) ensures a Test universe and these accounts on every startup:

Role in Test Login
Admin admin@lightspeed.dev (or LIGHTSPEED_PLATFORM_ADMIN_EMAIL)
Operator operator@lightspeed.dev
Contributor contributor@lightspeed.dev
Viewer viewer@lightspeed.dev

New accounts share LIGHTSPEED_PLATFORM_ADMIN_PASSWORD, defaulting to lightspeed-dev-password. Admin keeps its Platform administrator role; the other accounts receive only their listed universe role. Startup reuses existing accounts and the Test universe, restores the listed universe roles, and preserves existing passwords and content. Changing the password variable does not reset existing logins.

Set LIGHTSPEED_PLATFORM_DEV_SEED=false to disable these fixtures. Ordinary Platform startup and other launcher profiles leave them disabled. Seeding creates the runtime universe through the Platform’s deployment key, then records the accounts and memberships in the Platform database. A supplied key needs deployment/universes access for that step and the usual Platform permissions for interactive work.

Company sign-in with local Keycloak

The optional fixture in scripts/dev/oidc/ uses a loopback-only Keycloak container with a confidential client and PKCE required. From the repository root, start it and export the Platform configuration in the same terminal:

Terminal window
docker compose -f scripts/dev/oidc/compose.yaml up -d
export LIGHTSPEED_PLATFORM_OIDC_ISSUER=http://localhost:18090/realms/lightspeed
export LIGHTSPEED_PLATFORM_OIDC_CLIENT_ID=lightspeed-platform
export LIGHTSPEED_PLATFORM_OIDC_CLIENT_SECRET=lightspeed-local-oidc-secret
export LIGHTSPEED_PLATFORM_OIDC_USER_GROUP=lightspeed-users
export LIGHTSPEED_PLATFORM_OIDC_ADMIN_GROUP=lightspeed-admins
export LIGHTSPEED_PLATFORM_BASE_URL=http://localhost:5173
export LIGHTSPEED_PLATFORM_DEV_SEED=false
./dev.sh full

Open http://localhost:5173/app/; company sign-in starts automatically if you have no active session. Use hostname localhost for this fixture’s registered redirects. The imported accounts share password lightspeed-local-password:

Keycloak username Admission
sso-user Ordinary application access; initially no universe memberships
sso-admin Platform admin, with only the admin entitlement
sso-denied No application entitlement; sign-in is refused

Add sso-user to a universe through Members after its first sign-in. For the existing bootstrap admin, open http://localhost:5173/app/login directly and choose Admins. The fixture credentials and HTTP configuration are for local use only.

To try the manual login page, set LIGHTSPEED_PLATFORM_OIDC_AUTO_SIGN_IN=false before starting ./dev.sh full. Restart the launcher and refresh the browser after changing it; leave it unset or set it to true for automatic company sign-in. No frontend rebuild is needed.

Run the explicit live authentication check once Keycloak has started:

Terminal window
LIGHTSPEED_PLATFORM_OIDC_TEST_ISSUER=http://localhost:18090/realms/lightspeed \
npm run test:sso --workspace @lightspeed-ai/platform-backend

This uses a disposable in-process PostgreSQL database and the real provider’s code exchange. It checks admission, silent SSO renewal, admin demotion, entitlement removal, disabled accounts, absolute expiry and emergency access. It temporarily changes the fixture users and restores them afterward; don’t run simultaneous manual sign-in tests against the same fixture. The ordinary server tests separately exercise invalid signed responses, access-token claims, local memberships and protected auth routes without a live provider.

Stop just this provider with docker compose -f scripts/dev/oidc/compose.yaml down. Remove the exported OIDC variables and restart the Platform to return to local authentication. Company accounts remain distinct from local password accounts.

Choose the processes you need

Launcher profiles select local processes. They are separate from the agent profiles stored in a universe.

Command Use it for
./dev.sh full The complete editable product: runtime, Platform API and UI, Configurator MCP, local infrastructure, and the optional local daemon. This is the default.
./dev.sh runtime Rust runtime and daemon work against local infrastructure, without Platform or Configurator.
./dev.sh platform Platform API and UI work against the existing runtime named by LIGHTSPEED_API_URL. It starts local infrastructure but does not start that runtime.
./dev.sh demo UI work against the in-browser demo backend at http://localhost:5175/demo/. It needs neither Docker nor the Rust runtime.
./dev.sh docs Documentation with live reload at http://127.0.0.1:4321/docs/. Needs only Node and npm; doc and documentation are aliases.
./dev.sh infra Just PostgreSQL, pgAdmin, MinIO, and Temporal, for manual processes or live tests.

The supervisor tracks one application profile at a time. Use full for combined runtime and Platform work; starting a second supervised profile while the first is running is rejected. The infra command starts the shared services and returns without holding an application supervisor open.

You can inspect the commands and configuration for a profile before starting it:

Terminal window
./dev.sh --plan full

Planning still loads the development environment and can create the local daemon’s working directory. It does not start the services. The complete override table is in the environment-variable reference.

Both full and runtime-only profiles default to authenticated access. The launcher provisions a persistent CLI deployment key and, for full, a separate Platform service key when none is supplied. From a second terminal, run target/debug/lightspeed connect dev after building the CLI. No browser or manual key copying is required. Use --no-api-key-bootstrap to supply your own keys; migrations and universe setup still run. Explicit LIGHTSPEED_AUTH_MODE=single ./dev.sh runtime remains available for private local access. See Use Lightspeed from the terminal for setup, key replacement and universe selection.

Telegram and WhatsApp connector processes are opt-in. For example, LIGHTSPEED_CHANNELS_CONNECTORS=telegram ./dev.sh enables Telegram account discovery through the core API. Configure the corresponding account and credentials before expecting messages to flow. Bots and Channels core already run inside the Rust runtime; they don’t require the connector host to exist. See Channel connectors for connector development and setup.

Follow a change to its owner

Before changing a behavior, identify which layer decides it. A new user action may need a web control, an API operation, and a runtime implementation, but those pieces have different responsibilities.

If you are changing… Start here
Agent decisions, scheduling, or replayed session state crates/harness; keep decisions deterministic and represent effects as intents.
Public operation names, request fields, or response shapes crates/api; follow Changing contracts through generated consumers.
Durable execution, activities, or gateway behavior crates/temporal-workflow and crates/temporal-runtime; distinguish workflow decisions from activity I/O.
Provider transport, tool execution, or persistence The relevant adapter under crates/, such as llm-runtime, tools, or store-pg.
Product accounts, management routes, or the web experience platform/backend, platform/db, and platform/web; shared product types live in platform/shared.
Machine execution or provisioning The environment protocol, daemon, client, or provider; see Environment providers.

Use Architecture to understand those responsibilities, then the nearest Cargo.toml, package.json, and module tests to find the actual implementation. The workspace manifests remain the current inventory. A domain crate can validate a record without owning the database or network operation that eventually uses it.

For example, if a session control behaves incorrectly, trace the web request to the public API and then to the command it admits. Check whether the error is in the request, the admission policy, the reducer decision, or its effect. A UI workaround may hide a bug that a CLI caller can still reach. That same trace tells you where the regression test belongs.

Edit, check, and restart

Vite updates the web UI as you edit. The Platform backend runs through tsx watch and restarts on relevant source changes. The Rust runtime and daemon run through ordinary cargo run; the supervisor does not watch and rebuild them. Configurator and the optional connector host also run without watch mode in the full profile.

For a Rust change, run the focused test first, then stop and restart the profile to exercise the new executable:

Terminal window
cargo test -p harness
./dev.sh stop
./dev.sh

Replace harness with the crate you changed. Restarting recompiles changed Rust code and repeats startup migrations while retaining the infrastructure and its data. After changing startup environment variables, restart the relevant processes too.

For a web change, use its own checks while the development server stays open:

Terminal window
npm run typecheck --workspace @lightspeed-ai/platform-web
npm run test --workspace @lightspeed-ai/platform-web

The demo backend makes many visual and interaction changes easy to inspect without services. Validate against the full product when the change depends on real authorization, persistence, runtime progress, or service errors. Testing and evaluation explains how to widen checks as a change reaches more of the system.

For a manually launched Rust process or CLI, load the local connection settings into that terminal with source scripts/dev/env.sh. A manual server startup needs an explicit migration first:

Terminal window
source scripts/dev/env.sh
cargo run -p temporal-runtime -- migrate
cargo run -p temporal-runtime

Do this with the supervised runtime stopped so both processes don’t claim the same ports. The launcher implementation guide also shows split-role startup and a direct CLI conversation.

Inspect and preserve local state

The launcher prints readiness and process output in its terminal. Use ./dev.sh status to inspect the tracked supervisor and Compose services. If startup fails, the final error names the failing step, shows recent command output or the last health-check result, and suggests what to check next. Add --debug to the same command for launcher stack traces. The launcher stops its host processes after a failure and reports whether Docker infrastructure was left in place.

For durable work, the local Temporal UI is at http://localhost:8233; pgAdmin is at http://localhost:15080, and the MinIO Console is at http://localhost:29001. The service guide lists their endpoints and explains connecting to the two databases.

Stopping the application and deleting its data are separate operations:

Command Effect
Ctrl+C in the launcher, or ./dev.sh stop Stops tracked host processes; leaves Docker services and durable state available.
./dev.sh down Stops host processes and tears down the Compose services; retains their volumes.
./dev.sh down --volumes Also removes the Compose volumes and the data in them.
./dev.sh reset Recreates both local databases, migrates the runtime database, and clears the Lightspeed MinIO prefix. On success, also clears the launcher’s saved development credentials and CLI handoff. Stop the supervisor first.

Use reset for disposable development data when that is the intended outcome. After a successful reset, start ./dev.sh to provision development keys again, then run target/debug/lightspeed connect dev to refresh the CLI connection. Manual database resets leave the launcher’s saved credentials in place and require explicit key repair. A changed migration checksum requires understanding the schema history; deleting rows does not repair a ledger mismatch. See Changing contracts before editing migrations, and Upgrades and recovery when data must survive.

Work on the documentation

The manual sources live under docs/documentation/. The site reads them directly and publishes the generated API and workflow references alongside them. From the repository root:

Terminal window
npm install
npm run dev:docs

Open http://localhost:4321/docs/. Source edits refresh the site. Add new manual pages to the sidebar in docs/site/astro.config.mjs and give them a path from the documentation index.

Run npm run check:docs before submitting documentation changes. It checks the content adapter, Astro diagnostics, and the built site’s links and publication outputs. The site guide covers previewing the production build, Markdown exports, and deployment details.