Astrolabe

Introduction

A declarative macOS configuration framework that keeps a Mac in the state you describe.

Astrolabe is a Swift package for declaring the desired state of a macOS machine. You describe packages, launchd jobs, system settings, Jamf settings, and custom steps in a Swift body; Astrolabe runs as a root LaunchDaemon and continuously reconciles the real machine back to that declaration.

If you have written SwiftUI, Astrolabe will feel familiar. You declare what the machine should look like, not the steps to get there, and the framework keeps reality matching your declaration.

import Astrolabe

@main
struct WorkstationSetup: Astrolabe {
    var body: some Setup {
        Pkg(.catalog(.homebrew))
        Brew("wget")
        Brew("firefox", type: .cask)
    }
}

This says "Homebrew, wget, and Firefox should exist on this Mac." Astrolabe installs whatever is missing, then keeps checking. If something is removed later, the next pass puts it back.

Declarative, not scripted

Astrolabe is not a one-shot script runner. A script says "run these commands in this order." Astrolabe says "this state should exist" and keeps checking whether that remains true.

That difference matters over time. A script runs once and is done; if the machine drifts afterward, nobody notices. Astrolabe treats your declaration as the source of truth and reconciles the machine back to it on every pass.

The SwiftUI influence

The framework deliberately borrows from SwiftUI:

  • Astrolabe is the app entry point.
  • Setup is the declaration protocol.
  • @SetupBuilder turns multiple declarations into a tree.
  • @State, @Storage, and @Environment drive reevaluation.
  • Modifiers attach behavior and metadata to declarations.

Your body is a pure function of state, evaluated many times. When state changes, Astrolabe rebuilds the declaration tree, diffs it against the previous one, and applies only what changed — the same mental model as a SwiftUI view.

What you can do with it

Astrolabe is a good fit when you want a Mac to remain in a known state over time:

  • Install Homebrew packages and casks.
  • Install .pkg artifacts from a catalog, GitHub releases, or a custom source.
  • Write and optionally activate LaunchDaemons and LaunchAgents.
  • Apply system settings such as hostname and power management.
  • Apply Jamf settings such as computer name.
  • Persist local setup decisions with @Storage.
  • Attach user prompts, lifecycle hooks, and background tasks to declarations.
  • Ship a setup binary that can update itself from GitHub releases.

Platform requirements

Astrolabe is macOS-only:

  • Swift 6.2 or newer.
  • macOS 15 or newer, as declared in Package.swift.
  • Root privileges at runtime.
  • launchd, installer, pkgutil, softwareupdate, scutil, and Homebrew integration on the target Mac.

Where to go next

  • Getting Started builds and runs a minimal setup app.
  • Core Concepts explains the declaration tree, the synchronous tick, the identity model, and the "loop is retry" design.
  • Declarations covers the built-in building blocks: Brew, Pkg, LaunchDaemon, LaunchAgent, Sys, Jamf, Customized, Anchor, groups, and conditionals.
  • State and Persistence explains @State, @Storage, and @Environment.
  • Modifiers covers lifecycle hooks, priority, drift cadence, dialogs, tasks, and launchd sugar.
  • CLI and Operations covers daemon mode, inline mode, logs, reset, and troubleshooting.
  • Telemetry and Updates covers opt-in SigNoz telemetry and the sibling updater daemon.
  • Extending Astrolabe explains how to add custom package sources, system settings, inline steps, and new declarations.

New to Astrolabe? Start with Getting Started, then read Core Concepts before building anything complex.

On this page