---
title: "Distribution and deployment"
sidebarTitle: "Distribution"
description: "Understand Desk's binary-only installer, explicit Bun and Vite server modes, release assets, and container contract."
---

Desk distributes one public CLI with two explicit server modes:

| Command | Runtime | Intended use |
| --- | --- | --- |
| `desk serve` | Private compiled Bun runtime with embedded UI | Default local operation |
| `desk serve --dev` | Node and Vite with source UI | Desk development and debugging |

Both mount the same backend API. Neither command falls back to the other when its
runtime is missing or fails.

<Note>
`npm run build:distribution` invokes `fetch:moor`, which consumes the committed
four-target Moor release-asset pin and installs the selected host binary. The
runtime resolves explicit `DESK_MOOR_BIN`, then an attested same-release
`libexec/moor`, then an attested absolute `moor` found on `PATH`.
</Note>

## Binary-only installation

```bash
curl -fsSL https://github.com/BrainyBlaze/desk/releases/latest/download/install.sh | bash
desk serve
```

The installer:

1. detects macOS or Linux, x64 or arm64, and rejects unsupported libc;
2. checks its fixed shell prerequisites before creating a work directory;
3. downloads and authenticates the target-native bootstrap using receipts
   embedded in the version-bound installer;
4. validates canonical manifest schema 3 and the exact release inventory;
5. downloads only the selected prebuilt application, Node, and Moor assets;
6. safely extracts each archive into an empty staging directory;
7. verifies the application, native loader graph, platform floor, Node ABI,
   raw Moor receipt, and final release namespace;
8. probes the staged runtime, activates atomically, and smokes the public
   launcher.

The installer never downloads the source archive and never runs npm, Bun, Vite,
a compiler, or an operating-system package manager.

The default install root is
`${XDG_DATA_HOME:-$HOME/.local/share}/desk`. `DESK_HOME` overrides that root.
`DESK_BIN_DIR` overrides the launcher directory only when that canonical, safe
directory is already on `PATH` and no earlier command shadows it.

```text
desk/
├── releases/<version>/<install-id>/
│   ├── .desk-release
│   ├── node_modules/
│   ├── runtime/node -> node-toolchain/bin/node
│   ├── runtime/node-toolchain/
│   ├── dist/cli/main.js
│   ├── libexec/desk-standalone
│   ├── libexec/rg
│   └── libexec/moor              # pinned host-native Moor binary
└── current -> releases/<version>/<install-id>
```

The stable `desk` launcher resolves `current`, verifies that the release remains
under the managed root, and executes the release-bound Node runtime and CLI.

## Install lifecycle

- A first install does not expose a launcher until staging and smoke checks pass.
- An upgrade or explicit downgrade preserves the active instance until the new
  instance is verified.
- A same-version reinstall creates a new install ID; it never mutates the active
  directory.
- After successful activation, Desk retains the current and immediately previous
  valid instances and their referenced toolchains.
- Each installer is bound to one release. Downloading an older release's
  `install.sh` is therefore the explicit downgrade action.
- Any activation failure restores the previous `current` target and launcher.

Rerun the installer to upgrade or repair. Use the same installer for ownership-
safe uninstall:

```bash
curl -fsSL https://github.com/BrainyBlaze/desk/releases/latest/download/install.sh \
  | bash -s -- --uninstall
```

Uninstall preserves user configuration, projects, Moor sessions, credentials,
and optional tools.

## Release assets

Tagged releases publish exactly:

- `desk-vX.Y.Z-source.tar.gz`
- `desk-install-manifest.json`
- `install.sh`
- `SHA256SUMS`
- `desk-vX.Y.Z-install-bootstrap-linux-x64`
- `desk-vX.Y.Z-install-bootstrap-linux-arm64`
- `desk-vX.Y.Z-install-bootstrap-darwin-x64`
- `desk-vX.Y.Z-install-bootstrap-darwin-arm64`
- `desk-vX.Y.Z-application-linux-x64.tar.gz`
- `desk-vX.Y.Z-application-linux-arm64.tar.gz`
- `desk-vX.Y.Z-application-darwin-x64.tar.gz`
- `desk-vX.Y.Z-application-darwin-arm64.tar.gz`

`install.sh` is generated from the authenticated bootstrap receipts for that
release, so `releases/latest/download/install.sh` serves an installer of the same
generation as the release it installs.

The install manifest declares the independent source receipt plus exact
target-qualified bootstrap, application, Node, Moor, ABI, loader, and platform
authorities. It contains no caller-controlled URLs.

The source archive remains available for source access but is not an installer
input. Installation neither downloads nor observes it.

There is no separately installable server executable. The compiled runtime is a
private release component at `libexec/desk-standalone`.

## Build ordering

Contributors and CI pin Node 22.23.1, npm 10.9.8, and Bun 1.3.14.

```bash
npm ci
npm run check
npm test
npm run build:distribution
npm run smoke:serve-modes
npm run build
```

`npm run build:distribution` runs `fetch:moor` against the committed four-target
pin, runs the compiled-runtime build next, and runs the TypeScript CLI build
last. This order matters because Vite clears `dist/`. Run `npm run build` after
any later UI build to restore the Node CLI.

`npm run build:moor` is a separate source-build entrypoint. It validates
`vendor/moor/PROVENANCE.json` and the vendored snapshot digest before compiling
`libexec/moor`; the core/native CI workflow invokes this path.

The real smoke script proves:

- the default root responds without a Vite client route;
- `serve --dev` exposes the Vite client route;
- SIGINT and SIGTERM stop each supervised process group;
- an occupied port fails without an alternate listener or fallback;
- a controlled private-runtime exit status propagates through the CLI.

## Server options

Both modes accept flags:

```bash
desk serve --host 127.0.0.1 --port 5173
desk serve --dev --host 127.0.0.1 --port 5173
```

Precedence is flags, then `DESK_HOST` / `DESK_PORT`, then
`127.0.0.1:5173`.

## Container contract

The Docker image uses Node 22.23.1 in both build and runtime stages, builds the
full application at `/opt/desk`, and exposes the same CLI:

```bash
docker build -t desk:cli .
docker run --rm desk:cli help
docker run --rm -p 127.0.0.1:5173:5173 desk:cli
docker run --rm -p 127.0.0.1:5174:5174 \
  desk:cli serve --dev --host 0.0.0.0 --port 5174
```

The container binds `0.0.0.0` because port publication is controlled by Docker.
Publish it only on a trusted host interface. Desk has no built-in authentication.
The image packages and probes the pinned release asset installed as
`libexec/moor` during its `npm run build:distribution` builder step.
`DESK_MOOR_BIN` remains available as an explicit operator override.

## Host integrations

The installer owns the Desk build/runtime toolchains and bundled Moor
component. The following integrations remain optional and use the host user's
credentials:

- `codex`, `claude`, and `opencode` for agents
- `gh` for GitHub and Projects
- `rg` for fast search
- GPU telemetry commands

Read [Run Desk securely](/guide-deploy-securely) before remote access and
[Troubleshooting](/troubleshooting) for installer or runtime failures.
