Install and run the runtime
Apollia publishes no package on crates.io or PyPI yet, so you build it from a checkout. This guide is for developers. It takes you from a clone to a running daemon that can execute an agent, and then to the Tauri desktop app in dev mode, on macOS, Linux, or Windows. Plan for one longer first build (Rust compiles the workspace once), then rebuilds are incremental.
If you only want to run the finished desktop application, download a prebuilt installer instead: Install the desktop app.
Every command runs from the repository root unless stated otherwise.
Prerequisites
The build needs a Rust toolchain, Python, and Git on every platform. The
desktop app adds Node.js, the cargo tauri CLI, and a per-OS webview toolchain.
Install the shared tools first, then the OS-specific section for your machine.
Shared (all platforms)
-
Rust toolchain (stable). Install it from rustup.rs if you do not have
cargo. The repository pins an exact compiler inrust-toolchain.toml;rustupreads that pin and installs the matching toolchain automatically the first time you build inside the checkout, so you do not select a version by hand. -
Python 3.13, available as
python3. The runtime embeds Python to run the tools and workflows of packages, and the SDK installs into it. The checkout declares the exact version in.python-version. -
Git. Required to clone the repository.
-
For the desktop app only: Node.js 20 or newer (the project builds the UI on Node 22) with
npm, and thecargo tauriCLI:cargo install tauri-cli --version "^2" -
For local inference: the daemon serves local GGUF models through an embedded
llama-server. A packaged build bundles it; on a source build you needllama-serveron yourPATH(see the last section), no compiler required. Building the optional speech-to-text runner from source additionally needs CMake and a C/C++ compiler.
macOS
-
Xcode Command Line Tools, for the C/C++ toolchain and the WebKit webview the desktop app renders into:
xcode-select --install -
PyO3 must find the right interpreter at build time. If the default
python3is not the one you want, point it explicitly before building. With Homebrew Python: -
Building the optional speech-to-text runner from source needs CMake (
brew install cmake); the compiler comes from the Command Line Tools above. -
The desktop app requires macOS 13 (Ventura) or newer.
Linux (Debian / Ubuntu)
Install the build toolchain plus the Tauri v2 webview and system libraries. On Debian and Ubuntu:
sudo apt-get update
sudo apt-get install -y \
build-essential pkg-config libssl-dev \
libgtk-3-dev libwebkit2gtk-4.1-dev \
libayatana-appindicator3-dev librsvg2-dev \
libsoup-3.0-dev libjavascriptcoregtk-4.1-dev \
libasound2-dev libpulse-dev libjack-jackd2-dev \
python3-dev clang cmake file
What each group is for:
build-essential pkg-config libssl-dev: C/C++ toolchain and linking.libgtk-3-dev libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev libsoup-3.0-dev libjavascriptcoregtk-4.1-dev: the Tauri v2 webview and tray dependencies. Needed only for the desktop app.libasound2-dev libpulse-dev libjack-jackd2-dev: audio headers for the desktop app's speech-to-text capture. Needed only for the desktop app.python3-dev: headers for the embedded Python.clang cmake: needed only if you build the speech-to-text runner from source.
If you are building only the command-line runtime and not the desktop app, you can
skip the webview and audio groups and install just build-essential pkg-config libssl-dev python3-dev (plus clang cmake for the speech-to-text runner).
On other distributions install the equivalents of the same libraries. Package names differ (for example WebKitGTK 4.1, GTK 3, libayatana-appindicator, and librsvg development packages); verify the exact names for your distribution against the Tauri v2 prerequisites.
Windows
-
Microsoft C++ Build Tools (the "Desktop development with C++" workload from the Visual Studio Build Tools installer), for the MSVC compiler and linker.
-
Microsoft Edge WebView2 runtime. It is preinstalled on current Windows 11 and updated Windows 10. If it is missing, install the "Evergreen Bootstrapper" from Microsoft's WebView2 Runtime download page. Needed only for the desktop app.
-
CMake, only if you build the speech-to-text runner from source.
-
LLVM (provides
libclang.dllfor bindgen), only if you build the speech-to-text runner from source. Install withwinget install LLVM.LLVM, then point bindgen at it before building:$env:LIBCLANG_PATH = "C:\Program Files\LLVM\bin"Without
LIBCLANG_PATH, thewhisper-rs-sysbuild fails withUnable to find libclang. -
Run the commands below from a shell where
cargo,python,git, and (for the desktop app)npmare onPATH. The runtime primitives are tested on macOS and Linux; on Windows, verify the daemon commands on your machine and prefer a developer PowerShell that has the MSVC environment loaded.
Step 1: clone and build the daemon
git clone https://github.com/Apollia-OS/apollia-os.git
cd apollia-os
cargo build -p apollia-cli
Build the apollia-cli crate specifically. A workspace-wide build
(cargo build --workspace) also pulls in the desktop crate, which requires the
full webview toolchain from the platform sections above; scope the build to
apollia-cli to compile just the runtime.
The crate is named apollia-cli but the binary it produces is apollia-os, at
target/debug/apollia-os. That naming is deliberate; do not look for a file
called apollia-cli. Put the binary on your PATH so the rest of this guide can
call it by name:
export PATH="$PWD/target/debug:$PATH"
On Windows the binary is target\debug\apollia-os.exe; add target\debug to your
PATH the equivalent way.
This build talks to OpenAI-compatible servers, Ollama among them, and
serves local GGUF models through the embedded llama-server. On a source build
that engine has to be on your PATH, covered in the last section.
Step 2: install the SDK
An agent is a record declared in the apollia.toml of a package; the Python a
package brings is its tools and its workflows, written with the SDK. Install
the apollia package in editable mode into the same interpreter the runtime
uses.
Create a virtual environment first. Homebrew, Debian and Fedora ship Python as an
externally managed environment (PEP 668): installing into it directly stops with
error: externally-managed-environment, and the runtime runs the Python of packages with the
interpreter it finds on PATH, so the environment you activate here is the one it
will use.
python3 -m venv .venv
source .venv/bin/activate
pip install -e ./sdk
On Windows, activate with .venv\Scripts\activate instead.
Keep this environment activated in every terminal where you run apollia-os. If
you prefer a system-wide install and accept the consequences, pip install --break-system-packages -e ./sdk is the escape hatch, not the recommended path.
Step 3: configure a model backend
An agent that generates text needs a backend. Pick one path.
llm setup --local writes straight to the local database and works offline.
Every other llm subcommand, including backends create, reload and status,
talks to the daemon. If you take the server path, or want to check with llm status, start the daemon first with step 4 and come back here.
Server: register an OpenAI-compatible server (a self-hosted vLLM or LM Studio, or a LiteLLM gateway) with its address and, when it requires one, an API key. That is the only way such a server authenticates; there is no OAuth flow for one.
apollia-os llm backends create prod --provider openai \
--base-url http://10.0.0.5:8000/v1 --model qwen3-32b \
--api-key "$VLLM_API_KEY" --default
A key given as is moves to the secret store before the backend is saved, and the
backend database keeps only the fact that the store holds it. --api-key also
accepts a ${VAR} form, which names an environment variable resolved at
startup instead.
Use the model id your server serves for --model; the value above is only an
example.
Local: point the runtime at a .gguf file on your machine. This registers the
backend; the daemon serves it through the embedded llama-server (see the last
section for the llama-server requirement).
apollia-os llm setup --local --model /path/to/model.gguf
Either way, reload the backend registry and confirm the backend is visible. A
freshly configured backend does not appear in llm status until you reload:
apollia-os llm reload
apollia-os llm status
Step 4: start the daemon
apollia-os start --port 7771
On its first run the runtime creates its data directory at ~/.apollia. It
listens on a Unix socket (~/.apollia/runtime.sock by default, set to 0600
after binding) and on
127.0.0.1:7771. apollia-os start always binds TCP; --port chooses the
number, and omitting it takes [api].port of apollia.toml (7771 by default)
rather than leaving the port closed. On first boot it writes an API token to ~/.apollia/api-token;
TCP callers must present it as a bearer credential, while the Unix socket is
local-trust and needs none. Leave this terminal running and open a second one for
the next steps.
On Windows there is no Unix socket. The runtime serves a named pipe instead,
\\.\pipe\apollia-runtime-<user>, and the command line opens it without you
naming anything. TCP is bound there too, and the pipe is not local-trust: it
carries the same bearer token as TCP, because a pipe takes a default security
descriptor rather than the socket's 0600.
Step 5: run an agent
An agent ships in a package. Write the starting package, build it and install it:
apollia-os package new hello
apollia-os package build hello
apollia-os package install hello-0.1.0.apo
The starting package brings one agent and one Python tool. Then send the agent a task:
apollia-os run hello "hello from Apollia"
The agent answers with the model backend configured in step 3: an agent is a
mission the model carries out, so run needs one.
You should see its answer. To write your own agent from scratch, follow Your first agent.
Step 6: stop the daemon
apollia-os stop
Run the desktop app in dev mode
The Tauri desktop app is the graphical front end over the same runtime. To bring
it up from source, install the frontend dependencies once, then start the dev
build. This needs Node.js, the cargo tauri CLI, and the per-OS webview
prerequisites from the sections above.
Install the Svelte UI dependencies (a just recipe wraps npm ci):
just desktop-ui-install
# equivalent to: cd crates/apollia-desktop/ui && npm ci
Start the app in dev mode. This launches the Vite dev server for the UI and the Tauri shell with hot reload:
just desktop-dev
# equivalent to: cd crates/apollia-desktop && cargo tauri dev
The first cargo tauri dev compiles the desktop crate and can take a while;
subsequent runs are incremental. The window uses the system webview (WebKit on
macOS and Linux, WebView2 on Windows), so make sure your platform's webview
prerequisites are installed.
For local inference inside the dev app, make sure llama-server is on your PATH
(next section); the daemon the app embeds serves local GGUF models through it. See
Get the most from local inference.
Build a release desktop bundle
The just recipes below produce a distributable desktop installer (.dmg on
macOS, .deb/.AppImage on Linux, .msi/.exe on Windows). They run
bundle-cli.sh, which stages the Python runtime, the apollia-os CLI, the
speech-to-text runners, and a pinned llama-server binary.
Each recipe accepts two optional arguments:
| Argument | Role | Default (macOS / Linux / Windows) |
|---|---|---|
target | Rust triple passed to cargo tauri build | aarch64-apple-darwin / x86_64-unknown-linux-gnu / x86_64-pc-windows-msvc |
runners | Space-separated list of runner backends to build and bundle | cpu metal / cpu / cpu |
The runners value controls two things:
- Which
apollia-runner-{backend}sidecars are compiled and copied into the bundle. - Which prebuilt
llama-serverasset is downloaded. The script picks the first GPU backend in the list (metal,cuda,rocm, orvulkan); if none is present it falls back to CPU. SettingAPOLLIA_DESKTOP_LLAMA_BACKENDoverrides that choice and the list is not consulted, which is how thejustrecipes and the release pipeline bundle a Vulkan engine on Windows and Linux whatever the speech-to-text runners.
cpu is always included as a universal fallback. Add one GPU backend that
matches your hardware:
| Hardware | Typical runners value | Notes |
|---|---|---|
| Apple Silicon | cpu metal | Default macOS preset |
| NVIDIA (CUDA 12+) | cpu cuda | Builds the CUDA speech-to-text runner. The bundled LLM engine stays Vulkan: no bundle carries a CUDA llama-server, on any platform, and asking for one (APOLLIA_DESKTOP_LLAMA_BACKEND=cuda) stops the script on could not bundle llama-server (cuda). The installed application downloads the CUDA engine on demand from the engine channel; to bundle a build of your own, pass LLAMA_SERVER_DIR |
| AMD Radeon / Intel Arc | cpu vulkan | LLM and STT on GPU through Vulkan; the STT runner needs the Vulkan SDK (VULKAN_SDK) at build time |
| AMD Pro / Instinct + HIP SDK | cpu rocm | LLM and STT on ROCm where supported |
Platform presets:
# macOS Apple Silicon, Metal + CPU fallback (defaults)
just release-macos
# Linux x86_64, CPU only (default)
just release-linux
# Windows x86_64, CPU only (default)
just release-windows
Each preset takes the runner set as its one argument:
# Windows with Vulkan LLM (AMD / Intel / fallback NVIDIA)
just release-windows "cpu vulkan"
# Windows with the CUDA speech-to-text runner (NVIDIA); the engine stays Vulkan
just release-windows "cpu cuda"
# Linux with Vulkan
just release-linux "cpu vulkan"
# macOS with a custom runner set
just release-macos "cpu metal"
For a triple and runner set not covered by a preset, use the generic recipe:
just release-desktop x86_64-pc-windows-msvc "cpu vulkan"
just release-desktop x86_64-unknown-linux-gnu "cpu rocm"
just release-desktop aarch64-apple-darwin "cpu metal"
The bundled llama-server engine is fetched from the pinned upstream
llama.cpp release, which publishes builds for macOS (arm64 and x86-64), Linux
x86-64 (CPU, Vulkan, ROCm), Linux arm64 (CPU) and Windows x86-64 (CPU,
Vulkan). For any other couple, build llama.cpp yourself and pass
LLAMA_SERVER_DIR=<bin dir>; the recipe then bundles your build. The CUDA
engine is never bundled: it is published on the engine channel and downloaded
by the installed application.
On Windows, export LIBCLANG_PATH in the same shell before running any of
these recipes (see the Windows prerequisites above). On Linux, the speech-to-text runner additionally needs clang and
cmake in your package manager.
The bundle lands under target/<triple>/release/bundle/ (for example
target/x86_64-pc-windows-msvc/release/bundle/msi/ on Windows).
Local GGUF inference
Local models run through an embedded llama-server (upstream llama.cpp) that the
daemon spawns and supervises over its OpenAI-compatible HTTP API, with native tool
calling (--jinja) and continuous batching. The provider name stays llama-cpp.
A packaged desktop build stages llama-server automatically, next to the
speech-to-text runners, so nothing is needed there. On a source build the daemon
looks for llama-server on your PATH. Provide one of:
an upstream install that puts llama-server on your PATH, for example
brew install llama.cpp on macOS or a llama.cpp build on Linux.
The repository also has a just llama-server recipe. It does not satisfy this
prerequisite: it expects llama-server to be on the PATH already, and it starts
a separate server on port 8899 that the daemon does not talk to. It is a
developer bench for comparing against a hand-tuned server, not an install step.
If a local backend is configured but no llama-server is reachable, LLM calls
fail with a 503 Service Unavailable and a BackendUnavailable reason; put the
engine on your PATH to resolve it.
There is no download command for models. Obtain a .gguf file yourself (for
example from a model hub) and place it in ~/.apollia/models/, then point a local
backend at it with apollia-os llm setup --local --model <path.gguf>. The model
subcommands list and delete the files already present (list, delete),
query the Hugging Face registry (search, show), report the hardware and
rank the models this machine should run (hardware, recommend), and choose
the embeddings model (embeddings); see the CLI reference.
Speech-to-text is a separate, optional component. The apollia-runner sidecar,
built with a local-* feature (local-metal, local-cpu, local-cuda,
local-rocm, local-vulkan), runs whisper out of process; it no longer serves
LLM inference. A packaged build bundles it, and from source you build it only if
you want local dictation.
Next steps
- Write and run your own agent: Your first agent.
- Start the runtime at logon, without a terminal and without administrator
rights:
apollia-os service install(thenservice status, andservice uninstallto remove it), on macOS, Linux and Windows. - Run Apollia as a managed service: Deploy in production.
- Every flag on every command is in the CLI reference.