Skip to main content

How to run the Aucert Mac app

How to build, configure and run the macOS app and the aucert agent from a fresh clone, without asking anyone. If you only want to use a released build, skip to Install a DMG.

Every command below is run from the repository root unless stated otherwise.


Terminology​

Read this first. Most confusion about this app is vocabulary, not steps.

TermWhat it actually is
ConsoleThe Next.js web UI (frontend/apps/console). This is the entire interface — the Mac app has no bespoke UI of its own
Aucert.appA thin macOS shell: a WKWebView showing the console, plus a supervisor that starts the agent. It owns no device logic
Agentaucert agent — a Kotlin/JVM daemon. Finds your devices, talks to the relay, holds credentials. All device behaviour lives here
CLIThe same binary as the agent. aucert init, aucert devices, aucert run, aucert status, aucert logout, aucert agent
RelayA cloud service that lets a scan worker in Azure reach a device on your Mac. Neither side accepts inbound connections; both dial the relay
PipeOne tunnelled TCP connection through the relay, carrying adb traffic for exactly one device, for the lifetime of one scan
EnrollmentLinking this Mac to your Aucert account. Produces two credentials: an agent credential (offers your devices) and a user credential (starts scans)
Device refdvc_… — Aucert's stable id for one of your devices. Distinct from an adb serial, which changes
jlink runtimeA trimmed JRE built into the app/CLI bundle. You do not need Java installed to run them — only to build them

The single most useful thing to know: the app is a window around the console plus a launcher for the agent. If something device-related is broken, it is the agent, not the app.


Prerequisites​

NeedForCheck
macOS 13+running the app—
Xcode Command Line Toolsbuilding Swiftswift --version
JDK 21+building the agentjava -version
Bazelbuilding the agent jarbazel --version
Android platform-tools (adb)talking to devicesadb version

Missing adb? brew install --cask android-platform-tools.

You do not need Xcode.app itself, an Apple Developer account, or Java at run time.


Quick start​

Three commands, then sign in.

clients/macos/packaging/build-agent.sh     # 1. build the agent + its jlink runtime
clients/macos/packaging/build-app.sh # 2. build Aucert.app (embeds the above)
open .build/dist/Aucert.app # 3. run it

Then, in the app window: sign in, and approve the device-linking prompt.

By default the app points at http://localhost:3000, so you need the console running locally (tilt up — see tools/local/README.md). To point it at the deployed dev console instead:

AUCERT_CONSOLE_URL=https://dev-console.aucert.ai \
AUCERT_API_URL=https://dev-api.aucert.ai \
AUCERT_RELAY_URL=wss://dev-relay.aucert.ai \
open -a .build/dist/Aucert.app

The four build scripts​

All live in clients/macos/packaging/. Each is independently runnable; later ones call earlier ones when needed.

build-agent.sh — the agent bundle​

Builds the CLI's deploy jar (Bazel) and links a trimmed JRE around it, producing a self-contained aucert launcher that runs on a Mac with no Java installed.

clients/macos/packaging/build-agent.sh

This output is reused byte-for-byte by the next two scripts. Build it once.

build-app.sh — Aucert.app​

clients/macos/packaging/build-app.sh [output-dir]      # default: .build/dist

Compiles the SwiftPM target and assembles an .app bundle, copying the agent bundle into Contents/Resources/. That placement is what lets the app find its own agent instead of needing one on your PATH.

Produces an unsigned bundle. Fine for local use; macOS may warn on first launch (see Troubleshooting).

make-dmg.sh — the distributable​

clients/macos/packaging/make-dmg.sh

Builds Aucert.app if absent, then wraps it in a DMG. Signs, notarises and staples only when signing credentials are present in the environment — without them you still get a working unsigned DMG, so this is safe to run locally.

package-cli.sh — the CLI, without the app​

clients/macos/packaging/package-cli.sh

Tars the same agent bundle into a standalone archive: extract, run ./aucert --version. No .app, no macOS shell, no system Java. This is what CI and headless machines use.

macOS only. Cross-building a Linux runtime from a Mac is not possible with a stock JDK — jlink links against the current JVM's platform modules, and producing a foreign-OS image needs that platform's jmods.


Configuration​

Three URLs​

VariablePoints atDefault
AUCERT_CONSOLE_URLthe web UI the app displayshttp://localhost:3000
AUCERT_API_URLthe product API the agent enrols againsthttps://api.aucert.ai
AUCERT_RELAY_URLthe device-tunnel relaywss://relay.aucert.ai

Note the asymmetry, because it surprises people: the console URL is the app's setting and defaults to localhost. The API and relay URLs are the agent's settings and default to production. The app only forwards them to the agent it spawns — it does not use them itself.

So an app with no environment set shows a local console while its agent talks to production. That is deliberate (a released build should reach production without configuration), but it means you must set all three together when pointing at dev.

Per-environment values​

# Local development (console from `tilt up`)
AUCERT_CONSOLE_URL=http://localhost:3000
AUCERT_API_URL=http://localhost:8080
AUCERT_RELAY_URL=ws://localhost:8081

# Deployed dev
AUCERT_CONSOLE_URL=https://dev-console.aucert.ai
AUCERT_API_URL=https://dev-api.aucert.ai
AUCERT_RELAY_URL=wss://dev-relay.aucert.ai

# Production — the defaults; set nothing

Other settings​

VariableEffect
AUCERT_HOMEState directory: credentials, logs, the agent's IPC descriptor. Default ~/.aucert
AUCERT_LOGOFF / ERROR / WARN / INFO / DEBUG / TRACE. Default WARN
AUCERT_AGENT_BINARYUse an agent at this path instead of the bundled one. For developing the agent against a released app
AUCERT_MAC_INSPECTABLE=1 enables Safari Web Inspector on the embedded console. Essential for debugging UI

Setting them for a GUI launch​

Environment variables do not reach an app launched from Finder or Spotlight. Use open:

AUCERT_CONSOLE_URL=https://dev-console.aucert.ai open -a .build/dist/Aucert.app

For a persistent setting, the app also reads Info.plist keys — AucertConsoleURL, AucertApiURL, AucertRelayURL — where environment wins over plist. A release build with no keys set adds nothing, leaving the agent's own defaults intact.


Running the agent without the app​

Useful for CI, headless machines, or when you want to see the agent's own output.

aucert init         # enrol this machine — prints a code and a URL to approve it
aucert agent # run the daemon in the foreground
aucert devices # list the devices this machine is offering
aucert status # enrollment + agent state
aucert run # start a scan from the terminal
aucert logout # drop credentials

aucert --help and aucert <command> --help are authoritative; this list will drift, that will not.

On enrollment producing two credentials: aucert init mints both the agent credential and the user credential. Linking a Mac through the app's one-click flow mints only the agent one — which is why aucert run can report "this machine is not enrolled" about a machine the app shows as connected. Running aucert init afterwards resolves it.


Install a DMG​

  1. Open the DMG, drag Aucert to Applications.
  2. First launch: right-click → Open (unsigned builds are blocked by double-click).
  3. Sign in, approve the device link.

Confirm it worked: your device appears under Settings → Devices in the console, and aucert devices lists it.


Troubleshooting​

SymptomCauseFix
"Aucert" cannot be openedunsigned buildRight-click → Open. Or xattr -dr com.apple.quarantine /Applications/Aucert.app
App opens to a blank windowconsole URL unreachableIs tilt up running? Is AUCERT_CONSOLE_URL right?
Device not listed in the consoleagent can't see itadb devices first. An emulator must be booted before the agent finds it
Device shows ONLINE but scans fail relay_device_not_foundregistry says online, relay disagreesThe emulator stopped while the agent kept heartbeating. Restart the emulator
aucert run says not enrolled, but the app shows connectedonly the agent credential existsRun aucert init
build-agent.sh fails on JavaJDK missing at build timebrew install openjdk@21. Not needed at run time
Nothing in the UI respondsconsole JS crashedSet AUCERT_MAC_INSPECTABLE=1, relaunch, right-click → Inspect Element

Logs​

tail -f ~/.aucert/logs/agent.log          # agent — start here for device problems
log stream --predicate 'process == "Aucert"' # the Swift shell

AUCERT_LOG=DEBUG before launching gives far more.


Where things live​

Path
clients/macos/the Swift shell (Sources/AucertMac/)
clients/macos/packaging/the four build scripts
public/cli/the Kotlin agent + CLI — all device logic
~/.aucert/credentials, logs, agent IPC descriptor
.build/dist/build output

Further reading​

clients/macos/README.md (in the repo)why the shell is this thin, and the SPEC-076 rationale
public/cli/README.mdthe agent and CLI in depth
tools/local/README.mdrunning the backend + console locally (tilt up)
SPEC-076client architecture — one agent, three surfaces
ADR-028why a WKWebView shell rather than native UI