Products
Available

Loams Desktop and the loams CLI

The Electron desktop app that runs the console, a local engine and the agent daemon on your machine, and the one loams binary that runs, upgrades and administers a Loams stack.

What they are

Loams Desktop is one window with the whole Loams console in it. It runs a local engine for you (loams dev, supervised), manages local Postgres and TiKV stacks through Docker or Podman Compose, hosts Loams Studio on the local agent daemon loams-agentd, embeds the software factory apps, and connects to any other Loams server you add by URL, including a stack on your tailnet. It is Electron, and the console inside it is the same cordis console that runs at console.loams.dev.

The loams CLI is one binary. Today it is mostly the server: loams dev, standalone and cluster run the engine, and loams upgrade and loams migrate move a self-hosted stack from one release to the next while keeping its data. The client half that the design describes (profiles, stack create, product command groups, an MCP server, a one-line installer) is planned, not built.

Use the desktop if you want to try Loams on a laptop without assembling the compose stack, or if you want Studio with your local repositories and agent CLIs. Use the CLI to run an engine on a server, to mint API keys, and to upgrade a compose stack. Do not use either as your production control plane yet: the desktop's local stacks are development stacks, and the CLI has no remote management commands.

Status

Both are available in Loams 0.1.0, released 2026-10-18. As with all of 0.x, flags, layouts and formats may change between minor versions, and loams upgrade moves a stack between them. Studio, inside the desktop, is experimental.

ReleaseLoams Desktoploams CLI
0.1.0-preview.1 (2026-10-12)The Electron app on Linux: the cloud console against any server, a supervised loams dev with Data Studio, local Postgres and TiKV stacks, the factory apps, an agent panelLinux .deb, .rpm and .pkg.tar.zst, and an unsigned Windows .zip
0.1.0-preview.2 (2026-10-15)macOS (arm64, x64) and Windows (x64) beside Linux; Studio as the default modemacOS tarballs and the Windows zip beside the Linux packages
0.1.0 (2026-10-18, current)Studio's full surface through loams-agentd (experimental); the app reaches Loams Live on the engine's main portloams upgrade and loams migrate; git-remote-loams ships next to loams in every package

0.1.0 is the first release that keeps data across an upgrade: a preview.2 stack moves to 0.1.0 with loams upgrade. preview.1 to preview.2 kept no data.

Architecture

The renderer never holds a token. Electron main proxies the console's calls by path prefix to the active server, sends Studio's calls to the local loams-agentd with the daemon's owner token, and supervises the local engine.

The desktop

PartWhereWhat it does
Rendererweb/apps/console with the catalog/desktop.yml patchThe cordis console, sandboxed, no Node. Plugins that need the desktop require the desktop service, which only @loams/platform-electron provides (D658)
loams-app:// protocolapps/desktop-electron/src/main/protocolServes the console from loams-app://console/ui/ and proxies /api/, /v1/, /loams., /.well-known/, /health and /ready to the active server's origin, so the console keeps its cookies and router (D655)
Engine supervisorsrc/main/engineRuns loams dev on free loopback ports, waits for GetInstance, restarts with backoff (1 to 30 seconds, at most 5 restarts in 10 minutes), rotates engine.log, and scrubs secrets from the child's environment (D656)
Stack managersrc/main/stacksStarts the repository's Postgres and TiKV dev stacks with podman compose or docker compose, whichever it finds first
Studio and the daemonsrc/main/agentd, src/main/studioDiscovers or starts loams-agentd, forwards /loams.agentd.v1.* to its loopback Connect listener with the owner token after an allowlist check (D908), and drives the tray block and OS notifications
Factory host and vaultsrc/main/factoryForgejo, Zulip, Plane, GlitchTip, OpenPanel, Matomo, Langfuse and OpenObserve as read-only panels and embedded views; credentials encrypted with safeStorage, never sent to the renderer (D659)
Updatersrc/main/updateOff unless a feed is configured; a latest*.yml manifest must carry an Ed25519 signature against a key compiled into the app (D661)

When the active server is the local engine, the desktop answers /api/v1/instance and /api/v1/session itself (edition oss, features.local) and refuses the rest of /api/v1/* (D657), because the engine serves no control-plane REST. Cloud-only pages hide themselves.

The packaged app carries an engine built with --features live,durable,live-tikv,graph. If the Windows engine build or its --version check fails, the Windows build ships without a local engine and shows a "not available on Windows yet" state.

The CLI

crates/loams/src/main.rs is one clap tree:

CommandWhat it does
loams devEverything in one process, data in a local directory (--data-dir, default .loams); the HTTP API on loopback port 8080 by default
loams standalone --bucket <url>Everything in one process, data in an object-store bucket (s3://, gs://, file:///)
loams clusterOne node of a cluster, with --node-id, --roles (a subset of meta,log,query,worker,gateway), --peers and --bucket
loams warm <ns>/<collection>Warms a collection on the node that owns it
loams durable migrateCreates or updates Loams Durable's store schema
loams auth new-keyPrints a new API key once, and the hashed line for LOAMS_API_KEYS_FILE (--append <file> writes it, mode 0600)
loams upgradeUpgrades a self-hosted compose stack one release at a time: check, --to, rollback, status, snapshots
loams migrateThe server side of an upgrade: run, plan, status, verify, snapshot, restore, snapshots. In compose it is the one-shot migrate service
loams pg-control, pg-api-key, pg-runnerLoams Postgres's control plane, its keys and its compute runner. Built with the postgres feature, so they are in the loams-pg-control image, not in the packaged binary

The packages are built from the default feature set (es, flight, hnsw, live, qdrant). Durable, TiKV, the Postgres and MySQL wires and streaming gRPC are opt-in features, so a packaged loams refuses their flags; the compose images are built with them.

How it works

One console, in a window

The desktop does not fork the console. The renderer loads the same build the browser does, under a custom protocol, and Electron main makes it look same-origin by proxying API prefixes to whichever server is active. No redirect to another origin is followed, and cookie Domain attributes are stripped. That is why switching between the local engine, a stack on your tailnet and Loams Cloud is a server switcher, not three apps.

The local engine and stacks

The local engine is a child process, not a library (D656). The same loams binary runs here as on a server, a crash does not take the window down, and the supervisor restarts it. Live flags are passed only if the binary supports them: an engine that serves Loams Live on its main port gets no deprecated --live-listen, and if another engine already holds Live's default port, the desktop moves Live's own listener so this engine still starts.

The Postgres and TiKV stacks are the repository's own compose files (deploy/loams-postgres-dev, deploy/tikv), bundled with the app. They need Docker or Podman; without one, those pages say so and the rest of the app works.

The agent daemon

loams-agentd is the per-user Rust daemon that owns agent work (D780): Studio's threads, worktrees, terminals and approvals, and the harness CLIs. It came from a hard fork of an MIT-licensed desktop agent app, reduced to a headless daemon (D782, D783). It is a per-user service, never a system service (D784): systemd --user, a LaunchAgent on macOS, an HKCU Run entry on Windows. Until you agree to keep agents running in the background, it runs as the app's child and a quit drains it (D785). Linux linger is opt-in (D786).

Its RPC is loopback-only on an ephemeral port, with a per-user token checked before the WebSocket upgrade, any Origin refused and Host checked (D788). Electron main is the only general client, and the page reaches the daemon only through main's proxy. The same daemon is also published as the image ghcr.io/ostrium-labs/loams-agentd, for a remote Studio host (see Loams Studio).

Upgrades

loams upgrade --to V. Every step that touches data runs as loams migrate in a container of the target release's image; the CLI itself reads no store. A failure after the snapshot rolls back automatically with the door still closed and exits 10.

loams upgrade drives a compose stack from its directory (D934). It never opens a store itself: every data step is loams migrate … in a container of the target image, so the code that writes the new format is the code that ships with it.

  1. Preflight, bundle, pull. check's blockers must be empty and every service healthy. The target's compose bundle is downloaded and checked against the release's SHA256SUMS, and the images are pulled while the stack still serves. A failure here changes nothing.
  2. Close the door and quiesce. The Tailscale sidecars stop, so no client reaches the stack; then the writers stop (the daemon, the console, the Postgres computes, pg-control, pg-runner, the House, the engine, TiDB).
  3. Snapshot every store with the writers stopped (D930): TiKV with BR or as a cold copy, the bucket's few mutable pointer objects plus a GC root (the data objects are immutable, so this is cheap), Postgres drained and every timeline branched at its last record LSN, the House's directory, pg-control's records, Durable's SQLite, and the stack directory. Snapshots stay on the host, mode 0700, never uploaded.
  4. Install, restart, migrate, start, verify. The bundle replaces the stack files (.env, secrets/ and compose.override.yaml are kept), PD then TiKV restart, loams migrate run applies the release's migrations and records each in a ledger in the metastore's _system namespace (D928), the services start in order, and loams migrate verify reads every product's data.
  5. Open the door.

A failure in steps 8 to 11 restores the snapshot automatically and exits 10 (upgrade_failed_rolled_back). loams upgrade rollback does the same by hand and prints the window of writes it will lose first. rollback --keep-writes swaps the images back and keeps the data, but only when every migration of the step is Reversible and no third-party pin changed. If the CLI is killed, the same command resumes from .loams-upgrade/history.jsonl.

The engine, the House and pg-control refuse data they cannot read and exit 78 rather than start. Upgrades go one step at a time (D925): each release from the one before it, and from 0.1.0 on, any earlier patch of the same minor line. Third-party components stay pinned, and a target with an older PD, TiKV or TiDB is refused (D933). The hosted console supports the newest engine and the one before it; an older engine gets an "upgrade your engine" page (D938).

Key decisions and why

From the decision log; the designs are §37 (§19 is the Electron desktop), §50 (the daemon), §30 (the CLI) and §54 (upgrades).

DecisionWhatWhy, and what was rejected
D652The desktop ships on ElectronThe owner's ruling; the earlier native shell (a fork of a Rust GPUI app) had never launched from this repository and spoke its own contracts, while the console already existed. Tauri and the native track were set aside
D655Serve the console from loams-app://console and proxy API prefixes to the active serverThe console keeps its router, its base path, cookies and CSRF unchanged; no console fork
D656The local engine is a supervised loams dev sidecarProcess isolation, crash containment and the same binary as the CLI; embedding would tie Electron's lifecycle to the engine's
D659Factory credentials stay in main under safeStorage; IPC is a read-only op allowlistTokens never reach web content, and an app's UI can never drive the desktop
D661No updates without a signed manifest under a compiled-in keyA build can never install another project's binary
D663No telemetry; crash dumps stay localCarries D284's rule for the CLI
D676, D677Linux packages GPG- or SignPath-signed; Windows through SignPath; macOS unsigned and not notarized, with "Download" instead of self-updateThe owner has no Apple account. Windows builds without the SignPath secrets are unsigned too (below)
D780One agent system in a per-user Rust daemon, loams-agentdAgent turns must survive the window closing; Electron becomes a client
D788The daemon's RPC is loopback-only with a per-user token and refuses any OriginThe fork's IPC served any local process; the browser path is a separate listener (D909)
D281, D283One loams binary for server and client; an output and exit-code contractApproved, and partly visible today: loams upgrade already has stable error codes and exit codes
D923, D930, D932Data-keeping upgrades from preview.2 onward; snapshot first with writers stopped; rollback restores the snapshotThe owner's direction of 2026-10-13: a preview must be safe to keep using
D927migrate is a one-shot service of the loams image, and the engine starts only after it exits 0No separate migration image; an ordinary restart finds nothing to do
D935The fixed sequence, with the door closed during the dangerous partNo client sees a half-migrated stack

What is compatible

Supported
Desktop platformsLinux x64 and arm64 (.deb, .rpm, .pacman, .AppImage); macOS arm64 and x64 (.dmg, .zip); Windows x64 (NSIS installer, .zip)
CLI platformsLinux x64 and arm64 (.deb, .rpm, .pkg.tar.zst); macOS arm64 and x64 (.tar.gz); Windows x64 (.zip)
Linux distributions for the CLI packagesDebian and Ubuntu (.deb); Fedora, RHEL and openSUSE (.rpm); Arch and CachyOS (.pkg.tar.zst)
Container runtimesDocker or Podman with Compose, for the desktop's local stacks and for loams upgrade (docker compose or podman compose)
ElectronPinned exactly (44.4.5 in apps/desktop-electron/package.json)
systemdloams.service (loams dev, data in /var/lib/loams) and the loams@.service template, configured in /etc/default/loams

The server stack itself stays Linux containers. On macOS and Windows, run deploy/release with Docker Desktop; the patched TiDB image is amd64-only and runs emulated on Apple silicon.

How it compares

These are analogies, to place the pieces, not feature claims.

Loams Desktop and loamsThe closest familiar tool
Run the whole platform locallyThe desktop supervises loams dev and the compose stacks; docker compose up runs the full stackLike the Supabase CLI's supabase start, which runs Supabase's services locally in Docker. The Supabase CLI also manages migrations and deploys for a hosted project, which loams cannot do yet
Manage a hosted service from the terminalNot yet: login, keys, product commands and stacks are CL1, plannedLike Neon's CLI, neonctl, which manages projects and branches in Neon's cloud. loams has nothing comparable today
A desktop app around local containersThe desktop runs compose stacks, but its focus is the console, Studio and the engine, not container managementDocker Desktop manages containers and images in general; the Loams desktop uses Docker or Podman, it does not replace them
Upgradesloams upgrade snapshots, migrates, verifies and rolls back a self-hosted stackMost self-hosted database stacks leave this to the operator's own runbook

Where the others are better today: the Supabase and Neon CLIs are complete clients for a hosted product, with login, project management and scripting; loams is a server binary with an upgrade tool. Docker Desktop is signed and notarized; Loams' macOS builds are only ad-hoc signed and its Windows builds are unsigned.

What is missing and what is planned

  • Signing. Builds that are not signed by a trusted certificate say so in the release notes. macOS is ad-hoc signed and not notarized; Windows is unsigned and SmartScreen warns. The release pipeline can sign Windows and the Linux packages through SignPath and GPG once the owner adds the secrets (docs/release/desktop.md).
  • The client CLI (CL1, planned): configure and profiles, an API client, local stacks with product companions, loams live, pg, sql, graph and house command groups, login, keys, agent tokens, mcp serve and mcp install, embedded docs, loams doctor.
  • The installer and self-update (CLI2, planned): https://loams.dev/install.sh, prebuilt standard, full and cli variants, loams self-update with a signed manifest (D292 to D294). Today you install a package or unpack an archive.
  • The desktop runs migrate after an update (UP1 Task 18, D940): not built yet. Upgrades with loams upgrade are for compose stacks.
  • The daemon takes over supervision (DD1 DD1c, D790): today Electron main supervises the engine and the stacks. Bundling loams-agentd in every desktop package beside loams is D798; today the desktop release workflow bundles the engine only.
  • The console redesign (§59, plan CF1) makes the desktop feel less like a web page, with an agent-first home.
  • Local stacks use development settings: the Postgres dev stack uses default credentials and fsync = off (see deploy/loams-postgres-dev).

How to try it

Loams Desktop

Download from the GitHub release and check the files against DESKTOP-SHA256SUMS. On macOS, after installing:

xattr -dr com.apple.quarantine /Applications/Loams.app

On Windows, SmartScreen shows "Windows protected your PC": choose More info, then Run anyway. The app opens in Studio; switch to Console with Mod+Shift+M. The local engine is the default server; add a stack on your tailnet by its URL, such as https://loams.<tailnet>.ts.net.

The loams CLI

From the GitHub release, check the release checksums, then install the package for your system (0.1.0 shown; file names carry the release version):

sudo apt install ./loams_0.1.0_amd64.deb                        # Debian, Ubuntu
sudo dnf install ./loams-0.1.0-1.x86_64.rpm                     # Fedora, RHEL, openSUSE
sudo pacman -U ./loams-0.1.0-1-x86_64.pkg.tar.zst               # Arch, CachyOS
Expand-Archive .\loams-0.1.0-windows-x86_64.zip -DestinationPath loams
Get-Item .\loams\loams.exe, .\loams\git-remote-loams.exe | Unblock-File
.\loams\loams.exe dev

Run an engine and create an API key for the CLI or an SDK (with LOAMS_AUTH_MODE=apikey on the stack):

loams dev
loams auth new-key --label laptop --append keys.txt

As a service on Linux:

sudo systemctl enable --now loams

Upgrading a compose stack

From the stack's directory (the bundle's release/, with compose.yaml and .env):

loams upgrade check --to 0.1.0  # what it will do, and what would stop it
loams upgrade --to 0.1.0        # asks first; --yes to skip the question
loams upgrade status            # the stack's release, the ledger, the last attempt
loams upgrade rollback          # restores the snapshot; prints the writes it loses first

Do not upgrade by editing LOAMS_VERSION and running docker compose up: 0.1.0 recreates the Postgres safekeeper, which must be drained first. For a VM set up with byoc/install.sh, deploy/release/byoc/upgrade.sh user@host --to V runs the same upgrade over SSH.

Source

On this page