Gaea is a media server for the Mac. It serves the Media Engine Spec (MES) Image, Audio and Video profiles, and its models come as plugins:
- each plugin is a signed
.gaeapluginbundle that Gaea installs from a GitHub repo and runs in a process of its own; - Gaea does the MES front end, the queue, memory across processes, the plugins' lifecycle and the UI;
- the plugins do the generating.
Important
Gaea is alpha software in active development. Releases can still change how it behaves, so try it before you build on it, and read each release's notes before you update.
Download Gaea-<version>.zip from Releases, unzip it, and move
Gaea.app to Applications. It needs macOS 26 on Apple silicon, and it updates itself from these releases
(gaea update, or Settings → Updates). The command-line tool is Gaea.app/Contents/Helpers/gaea.
This is the operator's guide: one Mac running Gaea for the MES clients on it or on its network.
- As an app: open
Gaea.app. It lives in the menu bar, and its console has the Plugins, Models and System pages. Settings has the models root (General), adapters and updates. - Headless, for a studio Mac with no one at it:
Gaea.app/Contents/MacOS/Gaea --headless. Start it at login with a launch agent; an update relaunches it headless, on the same port and folder. - Where clients find it: MES on port 17630 (
--port), advertised over Bonjour (--no-advertisestops that).- Open, the default, it listens on this Mac only.
--pairedserves the network over TLS (--hostpicks the address). Each client pairs once: the app asks you, and a headless server with--approve-pairingsapproves every pairing, which is only for a network you trust.
- How it's configured: MES clients can't configure Gaea. You configure it in its console, Settings, and with
gaea, which talks to the running server over a socket on this Mac only (G-17). - Its folder is
~/Library/Application Support/Gaea:gaea.sqlite(plugins, models, trust, crashes and settings),Plugins/,Held/,Updates/,Crashes/and logs.GAEA_HOMEmoves it; keep that path short, because the socket's path is at most 103 bytes. - What it's doing:
gaea statusgives the server, plugins, workers, memory and crashes;gaea logsis Gaea's own log.
Every model is a plugin's. A plugin is a signed bundle from a GitHub repo, and each one runs in a process of its own.
- Adding one:
gaea plugins add https://github.com/xocialize-code/gaea-plugin-z-imageinstalls the newest full release (or… <version>) and turns it on. The plugins listed in this repo's CLAUDE.md are ours.GAEA_GITHUB_TOKEN=$(gh auth token)in Gaea's environment reads a private repo, and lifts GitHub's limit of 60 API calls an hour without a token, which a server with many plugins reaches when it checks them all. Gaea never stores the token. - Seeing them:
gaea pluginslists them, with each one's version, state and recent crashes.gaea plugins logs <id>shows its events and its worker's stderr. - Updates: Gaea reads every plugin's repo when it starts, and
gaea plugins checkreads them again.gaea plugins update <id> [version]installs the new version beside the current one, and switches when the plugin has no job.gaea plugins rollback <id>goes back to the version kept.- A release that needs a newer Gaea isn't offered.
- Switching off:
gaea plugins disable <id>keeps the plugin installed and takes its models out of what clients see;enablebrings them back.gaea plugins remove <id>uninstalls it. - Settings: a plugin's settings are on its row in the console's Plugins page, drawn from its manifest.
- On and off:
gaea modelslists every plugin's models. Research models and models whose licence needs accepting start off, andgaea models enable <id>turns one on. For a model whose licence asks each user to accept it too (LTX), clients see its terms and send their acceptance with the job; a job without it is refused withterms_not_accepted. - The models root is the one folder every plugin reads and downloads weights into: MLXEngine's store
(
~/Library/Application Support/MLXEngine/Models) unless you move it.gaea models root <folder>moves it, andgaea models root defaultgoes back. Settings → General does the same.--models-root <folder>moves it for one launch.- Workers restart when it changes, each one once its job ends.
- A model downloads its weights the first time a job needs them. Put the root on a fast volume: a plugin can refuse a lane whose weights sit on a volume too slow for it, and the warning says what it measured.
- Lanes: many models come in several quantizations ("lanes", such as bf16, int8, int4).
- Gaea loads a model's default lane when it fits in memory. Otherwise it loads the largest smaller lane that fits,
and the result carries a
lane_fallbackwarning naming both. gaea models lane <id> <lane>sets the default, and… defaultgoes back to the manifest's.- A request that names a lane (
x-gaea.lane) gets that lane or is refused; it never falls back.
- Gaea loads a model's default lane when it fits in memory. Otherwise it loads the largest smaller lane that fits,
and the result carries a
- Adapters (LoRAs):
gaea adapterslists those the plugins ship and those you added.gaea adapters add <hf-url> --model <id>adds one from Hugging Face, pinned to its commit and sha256. One that needs accepting starts off, andgaea adapters enable <id>accepts its terms.
Gaea runs one GPU job at a time across all its plugins, and it keeps workers warm so the next job doesn't reload.
- The budget is three quarters of the Mac's memory unless
--budget-bytes Nsets another for the launch. - Admission: Gaea admits each job against the budget, counting what every worker holds. When a job doesn't fit,
Gaea stops idle workers, least recently used first, to make room. A job that can't fit even then is refused with
no_capacity, and a model larger than the whole budget isn't offered. - Peaks: it learns each model's real peak from its runs, so a model that declares too little is charged what it used.
- Idle workers stop after 15 minutes (
--idle-seconds). - The ledger:
gaea ledgershows the budget, what each worker is charged and what it measures; the System page shows the same. - Wired memory: a worker keeps its weights wired while its job runs, as an in-process engine does, and lets them
go when the job ends. With one job at a time, that is never more than the job Gaea admitted.
GAEA_UNWIRED=1in Gaea's environment turns it off.
Gaea runs only plugins signed by a team you trust. It checks the signature, not the repo's URL, at install and again at every launch.
- Our team (Dustin Nielson, CFZS6RXUCP) is trusted from the start.
- A new team: its release is held, not installed. The console's Plugins page and
gaea trustshow the certificate's name, the team id, notarization and the repo.gaea trust approve <held-id>trusts the team and finishes the install. Later releases from that team then install without asking.gaea trust decline <held-id>drops the release.
- Removing a team:
gaea trust remove <team>stops its plugins and keeps them installed until you trust it again.
- Checks: Gaea checks its GitHub releases every six hours, and
gaea update --checkchecks now. Settings → Updates shows the same. - Installing:
gaea update [<version>]downloads the release, checks its signature, notarization and sha256, and installs it once no job is running or waiting. It waits a minute after the last job (--update-grace), so that job's client can fetch its outputs, then swaps the app and relaunches. - Going back: the version it replaced is kept in
Updates/, andgaea update --rollbackgoes back to it.gaea update --canceldrops an update that is still waiting. - Pre-releases are off;
gaea update --prereleases onincludes them. - Plugin versions: an update that would drop a protocol version an installed plugin uses is refused, naming the plugin.
A worker that exits when Gaea didn't ask it to has crashed. Gaea records each crash.
- The job: a job whose worker crashed is run once more on a new worker. If that one crashes too, the job fails and its error names both crashes. A streamed job isn't run again.
- The record:
gaea crashes [<plugin>]lists them, newest first, andgaea crashes show <id>gives one in full:- the plugin, version, model, lane and job;
- the signal or exit code;
- the last lines the worker wrote;
- macOS's crash report, copied to
Crashes/and summarised (a SIGKILL writes none).
- Quarantine: a plugin's third crash within ten minutes switches it off. Its models leave what clients see, its
jobs are refused with the reason, and
gaea plugins,gaea statusand the console say why. Find the cause in its crashes, thengaea plugins enable <id>(or its On toggle) clears the quarantine, and the count starts again. - macOS's own dialog: when Gaea runs as an app, macOS may also show "quit unexpectedly" for a crashed worker
(
gaea-…-worker). It is only macOS's notice. Gaea has already recorded the crash and dealt with the job, so you can close it.
The guide for plugin authors is AUTHORING.md in gaea-plugin-demo. It covers:
- the template;
- GaeaPluginKit;
- signing with your own Developer ID;
- releasing;
- what an operator sees when your team is new to their server.
The protocol between Gaea and a plugin is GPP-1, with its schemas in schemas/v1.
| Path | What |
|---|---|
| Docs/Gaea - PRD.md | The product requirements |
| Docs/Gaea - Plan.md | Decisions, architecture, the plugin protocol and the phases |
| spec/GPP-1.md | The Gaea Plugin Protocol v1 and manifest.json |
| Sources/ | The host: GaeaCore, the console, the app, the gaea CLI |
| Docs/Evidence/ | The acceptance runs behind each piece of work |
Apache-2.0.