# Localhost development updates

Lumi exposes one reusable runtime environment object:

```js
global.lumiRuntime
global.lumiEnvironment
global.lumiFrameworks.runtime
global.lumiFrameworks.environment
```

Useful fields include:

```js
{
  mode: "development" | "production",
  isDevelopment: boolean,
  isProduction: boolean,
  devMode: boolean,
  reason: string,
  allowsLocalDevelopmentUpdates(req): boolean
}
```

Runtime detection uses explicit `LUMI_DEV_MODE` first, followed by `NODE_ENV`, an explicitly loopback-bound `LUMI_HOST`, and whether Lumi is running from a source checkout. Production operators can always force production mode with `LUMI_DEV_MODE=false` or `NODE_ENV=production`.

The development update endpoint has a stricter boundary than the global mode flag. It is active only when all of the following are true:

1. Lumi is in development mode.
2. The request hostname is `localhost`, `127.0.0.1`, or `::1`.
3. The request originates from a loopback address.
4. The Companion device was paired from that exact localhost origin.

A source checkout exposed on a LAN therefore does not expose development artifacts to LAN clients.

## Checksum flow

The update service hashes source contents directly and never calls Git. Generated and mutable directories such as `bin`, `obj`, `node_modules`, `data`, logs, tests, documentation folders, build output, and update caches are excluded. README and changelog edits do not trigger binary updates.

Checksums are tracked independently for:

- Companion core;
- every directory under `companion/plugins`;
- Lumi server plugins related to Companion functionality.

Related server plugins are discovered through a matching Companion `plugin.json` ID or a server-side `companion_manifest.json`. This currently links Song Overlay and Lumi Transcription to their Companion components.

The aggregate build checksum combines the individual tracked component checksums. The installed Companion stores the checksums from its last localhost development update in `.lumi-dev-build.json` beside the executable.

When Companion checks for updates it sends only:

- its normal version;
- the aggregate development checksum;
- the per-component checksums.

Lumi responds with the changed component IDs. No source code or file inventory crosses the connection.

## Same-version update flow

When checksums differ on localhost, Lumi:

1. builds a self-contained Windows x64 Companion package from the current local source;
2. adds `.lumi-dev-build.json` to that package;
3. computes the package SHA-256 and exact size;
4. exposes the package through an authenticated localhost-only route;
5. returns a normal Companion update response even when the semantic version is unchanged.

Companion then uses its existing confirmation, download, checksum verification, staging, OBS-idle safety check, replacement, and restart flow. The build checksum is appended to the local staging directory so repeated same-version builds do not collide.

After restart, the installed checksum manifest prevents the same source state from being offered again.

## Requirements

The machine running Lumi must have a usable Windows .NET 8 SDK when a localhost development package needs to be built. The build runs lazily only after Companion asks for updates and its checksums differ.

The build cache is stored under:

```text
data/development-updates/companion/
```

Only the five newest checksum-addressed builds are retained by default.

## Configuration

Example local-only development setup:

```dotenv
LUMI_DEV_MODE=true
LUMI_HOST=127.0.0.1
```

`LUMI_HOST` is optional, but explicitly binding to `127.0.0.1` is recommended for a development instance that should never be reachable from the LAN.

Run the focused verification with:

```bash
npm run verify:dev-updates
```

## First adoption

An already installed Companion that predates this feature still uses the legacy
GET-only update check and cannot apply a localhost HTTP development artifact.
Build or install the patched Companion once through the normal development
workflow. After that first adoption, later same-version source changes use the
checksum update path automatically.
