# Apps and updates

MLX Node updates itself from a catalog that mlx.app signs; every download is checked against the catalog's SHA-256 and the app's Developer ID signature. Other makers' AI apps are in the AI App Store, inside MLX Node since 0.17.

MLX Node is the one download. Its **Apps** page lists MLX's own Mac apps in this catalog with their version and one button that does the next thing: Install, Update or Open. MLX Node itself is the only row. The code is `mac/MLX/Core/Hub.swift` (the catalog, installs, the notification centre) and `mac/MLX/UI/AppsView.swift` (the page).

> [!NOTE]
> AI apps, tools and models from other makers are in the [AI App Store](/store/overview), live on the web at [apps.mlx.app](https://apps.mlx.app) with its own signed [catalogue](/store/catalog). Since MLX Node 0.17 the Apps button opens the AI App Store window: MLX Node's own update lives under Installed and Updates, and other makers' apps install only from the maker's notarized download with the team and bundle id their listing pins. See [AI App Store links](/store/links).

## The catalog

```endpoint try
GET /api/apps
```

The answer is the catalog as a JSON string (`payload`), signed by the sequencer's key:

| Field | Type | Notes |
| --- | --- | --- |
| `payload` | string | The catalog: a JSON array, one entry per app. |
| `sig` | string | Ed25519 signature, hex, over SHA-256 of `"mlx-apps-v1\n" + payload`. |
| `key` | string | The sequencer's public key, hex. When MLX Node has pinned the sequencer's key while witnessing the ledger, it refuses a catalog signed by any other key. |
| `rev` | string | 12 hex characters that change whenever any version, status, rollout or note changes. |
| `at` | number | When the catalog was built, in ms. |

Each app in `payload`:

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string | The app's id: `node` for MLX Node. |
| `name`, `blurb`, `page`, `icon` | string | What the Apps page shows. |
| `bundleId`, `team` | string | What the installer checks in the app's signature: `app.mlx.mac` for MLX Node; team CCKXS9W488. |
| `fileNames` | string[] | Names an installed copy may have, newest first. |
| `version`, `minOS`, `size`, `sha256`, `url` | | The public build: a notarized disk image. `null` while there is none. |
| `notes` | string | What's new, shown under the app. |
| `status` | string | `available`, `new` (a blue dot until seen), `beta`, or `soon` (listed, not installable). |
| `rollout` | number | 0–100: the share of Macs that see this version as an update. |

The heartbeat reply carries `catalogRev` and `inboxRev`, so MLX Node fetches the catalog and the announcements only when they change (and at least every six hours).

### Rollout

A Mac sees a version as an update when the first two bytes of SHA-256 of `"<app>:<version>:<device public key>"`, read big-endian, modulo 100, are below `rollout`. The same Mac always lands on the same side, so a 20% rollout reaches the same fifth of Macs until it widens. A new install always gets the current version.

## Installing and updating

:::steps
### Download
MLX Node downloads the disk image from the catalog's `url` and checks its size and SHA-256 against the catalog.
### Check
It hands the image to its installer service (`MLXUpdater.xpc`, the only part of MLX Node outside the App Sandbox). The service mounts it read-only and checks the app inside: a Developer ID signature from team CCKXS9W488, the catalog's bundle id (only `app.mlx.*` apps, never MLX Node through this path), and a version newer than the installed one.
### Install
The app is copied to the same folder as the installed copy (or to Applications, or ~/Applications for a new install) and swapped in. An app that is running is never replaced: the page says "Quit to update".
:::

**Automatic updates** are on by default (Apps page → Update automatically). MLX Node updates itself once per version while its panel is closed; other apps are updated while they aren't running.

## The menu bar dot and the notification centre

The icon shows a red dot when an installed app (MLX Node included) has an update, and a blue dot for something new: an app not installed yet, an announcement or unread wallet news. The bell in the panel opens the notification centre: updates, new apps, announcements and wallet news, newest first.

```endpoint try
GET /api/inbox?app=0.12.0&seat=free
```

Announcements, written by MLX in Admin → Announcements. `app` (MLX Node's version) and `seat` (`free` or `dedicated`) narrow the list to the announcements meant for that audience; nothing else is sent. What was read stays on the Mac.

| Field | Type | Notes |
| --- | --- | --- |
| `items` | array | Newest first, up to 50: `{ id, title, body, link?, at, until?, audience, minApp?, maxApp? }`. `link` is an https page, or an app id (such as `node`) that opens its row on the Apps page. |
| `rev` | number | The newest announcement's time; the heartbeat's `inboxRev` carries the same value. |

## Links

| Link | What MLX Node does |
| --- | --- |
| `mlx://apps` | Opens the Apps page. |
| `mlx://install?app=<id>` | Opens the Apps page at that app. It never installs by itself: the owner presses Install. |

From MLX Node 0.17, `mlx://store` and `mlx://install?app=<a>,<b>` open the AI App Store window instead; see [AI App Store links](/store/links). See [Links](/node/links) for the others.
