Aileron ControlPlane

Building from Source

End users install pre-built binaries via Homebrew, apt, yum, or apk (see Getting Started). This page is for contributors who want to build everything locally from a fresh clone.

Prerequisites

Expand each one for per-OS install commands.

Aileron's modules require it. go version should report at least go1.25.0.

brew install go

All build commands go through task. See taskfile.dev for other install options.

brew install go-task

The webapp and docs targets build through pnpm, so task build will fail without them. The simplest setup is corepack enable after installing Node, then corepack prepare [email protected] --activate.

brew install node
corepack enable
corepack prepare [email protected] --activate

Get lint feedback locally ahead of CI.

brew install golangci-lint

GitHub's CLI, used by the PR workflow.

brew install gh

Only required if you're touching the Docker images under deploy/.

Docker Desktop is the simplest path.

brew install --cask docker

Build everything

task build

This is the all-in-one entry point. It builds the three binaries, the docs site, the webapp, and the Docker containers. Output lands under build/. The first run pulls Go modules and pnpm installs the webapp and docs dependencies; subsequent runs are incremental.

Build a single binary

Each binary has its own Taskfile entry. Output is the same build/<binary> path:

task build:cli      # aileron
task build:mcp      # aileron-mcp
task build:enclave  # aileron-enclave

The CLI build embeds the webapp. If you’ve made changes to it, regenerate first (see the next section).

Embedded assets

The local webapp

The daemon ships with the local webapp embedded via go:embed from internal/app/webapp_dist/. To pick up webapp changes in the daemon:

task build:webapp   # builds webapp/, copies output into internal/app/webapp_dist
task build:cli      # re-embeds the new webapp bytes into the daemon binary

For iterating on the webapp without rebuilding the daemon every change, use task dev:webapp. The dev server at localhost:5173 hot-reloads; aileron launch continues serving the embedded build.

Generated API types

The daemon’s HTTP API is defined in internal/api/openapi.yaml. Server interfaces and request/response types are generated:

task generate:api

Per the project’s CLAUDE.md, the spec is the source of truth. Hand-editing internal/api/gen/server.gen.go is not supported; any API change starts in the spec.

Build the docs site

task build:docs   # static build under docs/dist/
task dev:docs     # live dev server at localhost:4321

The docs site is Astro + Svelte. Pages live under docs/src/content/docs/ (Markdown / MDX); the sidebar is configured in docs/src/lib/navigation.ts. Build artifacts are not committed.

Build for release

task release:snapshot   # GoReleaser snapshot (no publish)

This produces the same artifacts CI ships on tag pushes: .deb, .rpm, .apk, and the Homebrew formulas. The snapshot run does not publish anything; it’s the dry run.

Reproducibility notes

  • The go.work workspace pins the Go module set across cmd/, internal/, sdk/, and test/. go build ./... from the root won’t work; always invoke from a specific module directory or use task.
  • The four binaries are version-coupled. A task build is the supported way to get a matched set; ad-hoc go build against one of the four is fine for iteration but the resulting binary is only guaranteed to talk to a same-commit peer.

See also