
Terraform changed how teams think about cloud infrastructure: declare the desired state, apply it, and let the tool keep reality in sync. Astrolabe brings that same model to macOS.
If you run Macs in a fleet — inference nodes, CI runners, developer workstations, kiosks — you've probably stitched together shell scripts, MDM profiles, and manual checks to keep machines in shape. Astrolabe replaces that patchwork. Declare your macOS configuration in Swift with a SwiftUI-like syntax, and Astrolabe continuously enforces the state you described.
No setup scripts. No periodic audits. Just a declaration that enforces states.
Mac fleets are everywhere. The tooling still isn't.
Frontier AI labs rack Mac minis as inference servers. Platform teams run Mac Studios and Mac Pros as CI builders. Enterprises deploy MacBooks, kiosks, and shared workstations at scale.
These teams share the same problem: every machine needs to stay in a known, reproducible state — packages installed, services running, settings locked — not just at imaging, but continuously.
Traditional MDM handles enrollment, profiles, and compliance baselines well. But when you need to guarantee a specific LaunchDaemon is running, a Homebrew package is present, or a system setting hasn't drifted since last night, MDM is the wrong layer. It was designed for policy distribution, not runtime enforcement.
Astrolabe is built for that layer.
What Astrolabe is
Astrolabe is an open-source, declarative macOS configuration framework written in Swift. You describe the state a Mac should be in. Astrolabe runs as a root LaunchDaemon and continuously reconciles reality back to that description.
If you've written SwiftUI, the model will feel immediate:
Homebrew, wget, Ollama, a health-check daemon, a hostname, a power setting — all declared in one place. Astrolabe installs whatever is missing, starts whatever should be running, and keeps checking. If something drifts, the next pass puts it back.
A shell script runs once and hopes nothing changes. Astrolabe treats your declaration as a continuous source of truth.
Why this matters
Drift correction, not drift detection
Every tick, Astrolabe compares live machine state against your declaration. Package uninstalled? Daemon crashed? Setting changed? Corrected on the next pass. The reconciliation loop is the monitoring — no separate tool required.
Configuration as code
Your fleet configuration lives in Swift — versioned in Git, reviewed in PRs, deployed like any other infrastructure artifact. No web console. No XML profiles. Just Swift code.
Why Swift
Swift isn't just a convenience choice. Its memory safety, strict type system, and compile-time guarantees mean your fleet configuration can't silently mishandle data, overflow a buffer, or pass the wrong type to a system API. That matters when your code runs as root on every machine in the fleet.
And because Swift bridges directly to C, Astrolabe can drop into low-level system work — calling Darwin APIs, interacting with IOKit, or invoking launchctl internals — without shelling out or marshaling through an intermediary. You get the safety of a modern language with the efficiency of native system access.
Runtime guarantees
Astrolabe doesn't configure a machine once and walk away. It runs as a persistent LaunchDaemon and provides a runtime guarantee: the state you declared will be maintained continuously. For inference nodes that need to stay healthy for weeks without human intervention, that's a fundamentally different operational model.
Composable, fine-grained control
Declare individual packages, LaunchDaemons, LaunchAgents, system settings, and Jamf properties. Compose them like SwiftUI views — group, branch conditionally, attach lifecycle hooks, and extract reusable modules.
Profile-based MDM can't express this. The smallest unit is usually an entire policy. Astrolabe gives you per-package, per-daemon, per-setting control.
The SwiftUI mental model
Astrolabe borrows from SwiftUI deliberately:
SwiftUI | Astrolabe |
|---|---|
|
|
|
|
|
|
|
|
|
|
Modifiers attach behavior — priority, drift cadence, lifecycle hooks, dialogs, and background tasks. Your body is a pure function of state. When state changes, Astrolabe rebuilds the tree, diffs it, and applies only what changed.
Built-in declarations
Astrolabe ships with the building blocks fleet operators reach for most:
Homebrew —
Brew("ffmpeg"),Brew("firefox", type: .cask).pkginstallers — from Homebrew's catalog, GitHub Releases, or custom sourcesLaunchDaemons and LaunchAgents — define, install, and keep them alive
System settings — hostname, power management, energy schedules
Jamf properties — computer name and other managed fields
Custom steps — anything that doesn't fit a built-in declaration
Declarations are Swift protocols. Extend Astrolabe with your own package sources, system settings, and inline steps.
Self-updating
Once you ship an Astrolabe binary to your fleet, it can keep itself current. Opt in with a simple configuration:
Astrolabe installs a sibling updater daemon that checks your release source, downloads newer packages, verifies signatures, and restarts the main daemon — zero manual intervention. Push a new release to GitHub, and your entire fleet picks it up.
Battle-tested at Photon
Astrolabe isn't a side project we're releasing cold. We've run it internally at Photon for over six months.
Photon provides iMessage APIs for AI agents, backed by a fleet of Macs that relay iMessage traffic. Every machine in that fleet needs the right services running, the right packages installed, and the right system configuration locked in — continuously, not just at setup.
Before Astrolabe, that meant shell scripts, manual checks, and a growing ops burden. After adopting it, we cut ops time on our macOS fleet by 60%. We no longer need dedicated DevOps for fleet maintenance. Rolling out a new feature is a code change and a release — Astrolabe's self-update mechanism propagates it across the fleet. Rolling back is the same. And every machine stays in the state we designed, not the state it drifted into.
That's the confidence we want every team running Macs at scale to have.
Who it's for
AI/ML labs running Mac fleets for inference, training, or research. Every node in a known state, packages pinned, services guaranteed, drift corrected — without babysitting.
Enterprise IT and DevOps teams that have outgrown what MDM profiles can express. Infrastructure-as-code for macOS — version-controlled, composable, testable — that works alongside your existing MDM, not instead of it.
Platform engineers managing CI fleets, kiosk deployments, or shared developer machines. Any Mac — mini, Studio, Pro, or laptop — that needs to stay in a declared state without someone SSHing in to fix it.
Get started
Astrolabe is fully open source under the MIT license.
Read the docs → photon.codes/astrolabe
Clone the repo → github.com/photon-hq/Astrolabe
Requirements: macOS 15+, Swift 6.2+
Declare what your Macs should look like. Astrolabe keeps them there.


