Links
MLX Node handles mlx:// links. A Mac is linked to a wallet through the wallet's ?link= page and a bind_device transaction.
mlx:// links
LinkCommand.parse in mac/MLX/Core/Yield.swift reads every mlx:// link MLX Node is asked to open:
| Link | What MLX Node does |
|---|---|
mlx://apps, mlx://install?app=<id> | opens the Apps page, at that app (0.11; never installs by itself). See Apps and updates |
mlx://store, mlx://store?app=<slug>, mlx://install?app=<a>,<b> | MLX Node 0.17 or later: opens the AI App Store window, at a listing or with up to 20 listings picked to install (never installs by itself). See AI App Store links |
any other mlx:// link, such as mlx://open | opens the panel (in MLX Node 0.16 and older, mlx://store too) |
The action can be the host (mlx://apps) or the path (mlx:apps, mlx:///apps). Names are read without regard to case.
open "mlx://apps"Who can open these links
Any app on the Mac can open an mlx:// link. A URL scheme carries no caller identity, so none of these links does anything the owner hasn't pressed for: they open the panel, the Apps page or (from 0.17) the AI App Store, and nothing installs by itself.
Linking a Mac to a wallet
The link request
MLX Node signs a link request with its device key (linkURL in mac/MLX/Core/API.swift) and opens the wallet with it:
https://wallet.mlx.app/?link=<base64url of the JSON below>{ account, device, name, chip, memoryGB, os, ts, sig }account is a wallet name, or * for an open request: one the owner approves from whichever wallet they unlock (ANY_WALLET). MLX Node sends open requests. device is the Mac's public key, name its computer name, ts the time in ms. sig is ECDSA P-256 over SHA-256 of this canonical JSON (linkMessage in lib/chain/device.ts):
{"account":"*","chain":"<chain id>","chip":"<chip>","device":"<pk>","memoryGB":<memoryGB>,"name":"<name>","os":"<os>","ts":<ts>,"type":"mlx-device-link"}The server cleans the name before it checks the signature (control characters removed, trimmed, cut to a maximum length), so MLX Node sends it already clean.
In the wallet
The wallet's link sheet (LinkDeviceSheet in components/wallet/Macs.tsx):
- checks the request is for this wallet or open, recent, and signed by the device;
- shows the Mac: name, chip, memory, macOS version;
- looks the device up with
GET /api/device/<pk>, and says so if connecting moves it from another wallet; - asks for the wallet's passkey or recovery phrase, unless the wallet was unlocked or created a moment ago in this same flow;
- sends the
bind_devicetransaction.
{ type: "bind_device", device, name, chip?, memoryGB?, os?, ts, proof: <the request's sig> }Inside MLX Node's panel, the wallet then tells the app with a linked message.
On the ledger
The ledger checks bind_device before it records it:
tsis close to the transaction's time;proofis the device's signature over the link message for this wallet, or for*;- the proof wasn't used before (
devproof:<sha256 of the proof>), andtsis newer than the Mac's current link. Both apply to links fromBIND_V2_ATon, so an open request seen on the chain can't be replayed from another wallet; - the wallet has fewer than 32 devices.
If the Mac was linked to another wallet, it is removed from that one. A Mac belongs to one wallet at a time. The Mac's record in the wallet holds its key, name, chip, memory, macOS version and the link's time and block.
MLX Node polls GET /api/device/<pk> until at grows, then carries on with setup. See Device lookup.
Unlinking
The wallet sends unbind_device with the device's key. The Mac gets no more jobs for that wallet until it is linked again.
What is public
A Mac's name stays private. Public reads of transactions and accounts show only the kind of Mac ("Linked a MacBook Air"), never its name. The owner sees names in their own wallet and in MLX.app, through signed requests.