macOS menubar hub that coordinates between Chisel, Atem, and AI agents. Receives annotation tasks from the browser, routes them to the right Atem instance, tracks task status, and relays voice-coding sessions -- talk to your coding agent from anywhere.
Download the .pkg installer from Releases, or build from source.
Prerequisites: macOS 14+, Xcode Command Line Tools, CMake.
git clone git@github.com:Agora-Build/Astation.git
cd Astation
# 1. Build the C++ core library (CMake auto-downloads Agora SDK from SPM distribution)
mkdir -p build && cd build
cmake .. -DBUILD_TESTING=ON
make -j$(sysctl -n hw.ncpu)
cd ..
# 2. Build the Swift app (SPM auto-downloads Agora frameworks)
swift build -c release
# Binary at .build/release/astationWhat happens during build:
- CMake detects missing Agora SDK and downloads 7 xcframeworks from
https://download.agora.io/swiftpm/AgoraRtcEngine_macOS/4.6.2/ - Swift Package Manager resolves
AgoraRtcEngine_macOSdependency automatically - No manual SDK downloads needed!
Troubleshooting:
- If CMake fails with "SDK not found": Run
cmake ..again to retry download - If SPM fails: Try
swift package resolve --force-resolution - Clean build:
rm -rf build third_party/agora .build && swift build
Offline / pre-downloaded SDK
- Skip auto-download and use a local SDK root:
cmake -S . -B build -DAGORA_SKIP_DOWNLOAD=ON -DAGORA_SDK_DIR=/path/to/sdk - Expected layout:
/path/to/sdk/rtc_mac/<Framework>.xcframework/...
Linux/Windows builds:
- C++ core only (no Swift app on these platforms)
- CMake does NOT auto-download on Linux/Windows
- Download SDK manually:
- Linux: https://docs.agora.io/en/sdks?platform=linux → extract to
third_party/agora/rtc_linux/ - Windows: https://docs.agora.io/en/sdks?platform=windows → extract to
third_party/agora/rtc_win/
- Linux: https://docs.agora.io/en/sdks?platform=linux → extract to
Astation runs as a macOS menubar app with a WebSocket server. Multiple Atem instances connect to it, and the hub routes work to the focused (or first available) Atem.
When a user draws annotations in Chisel and clicks "Ask Agent to Work on It":
Chisel (browser)
↓ POST /api/dev/save-mark
Express middleware (saves .chisel/tasks/{id}.json + .png)
↓ WS markTaskNotify {taskId, status, description}
Astation hub
↓ picks target Atem (focused > first available)
↓ WS markTaskAssignment {taskId}
Atem
↓ reads task from local disk
↓ spawns Claude Code with prompt
↓ WS markTaskResult {taskId, success, message}
Astation hub
↓ updates task tracker
Messages carry only IDs, status, and descriptions -- no images or file lists flow through Astation.
| Message | Direction | Purpose |
|---|---|---|
markTaskNotify |
Chisel -> Astation | New task available (with summary for display) |
markTaskAssignment |
Astation -> Atem | Route task to a specific Atem |
markTaskResult |
Atem -> Astation | Report task completion/failure |
statusUpdate |
Astation -> Atem | Connection status on connect |
heartbeat / pong |
Atem <-> Astation | Keep-alive |
voice_toggle |
Astation -> Atem | Voice input state |
video_toggle |
Astation -> Atem | Video state |
atem_instance_list |
Astation -> Atem | Broadcast connected peers |
auth_request / auth_response |
Atem <-> Astation | Authentication grant flow |
Atem instances authenticate via a deep-link flow:
- Atem sends
auth_requestwith session ID, hostname, and one-time password - Astation presents the request to the user for approval
- On approval, sends
auth_responsewith session token
Astation captures mic audio via AVAudioEngine, runs WebRTC VAD, streams through Agora RTC, and pushes transcriptions via Agora RTM to the active Atem instance. See designs/data-flow-between-atem-and-astation.md in the Atem repo.
Sources/
CStationCore/ # C shim for Swift-to-C++ bridge
Menubar/
main.swift # App entry point
AstationApp.swift # App lifecycle, wiring handlers
AstationHubManager.swift # Business logic, task tracking, routing
AstationMessage.swift # Codable message types (encode/decode)
AstationWebSocketServer.swift # NIO WebSocket server
AuthGrantController.swift # Auth request approval flow
CredentialManager.swift # AES-GCM encrypted credential storage
AgoraAPIClient.swift # Agora REST API integration
RTCManager.swift # Agora RTC audio management
HotkeyManager.swift # Global hotkeys (Ctrl+V voice, Ctrl+Shift+V video)
StatusBarController.swift # macOS menubar UI
core/
src/astation_core.cpp # C++ core (session management)
src/astation_rtc.cpp # RTC audio processing
include/ # C headers
server/
src/main.rs # Rust HTTP server (auth web fallback)
- Swift Package Manager: WebSocketKit, SwiftNIO, AgoraRtcEngine_macOS (auto-downloaded)
- C++ Core: CMake, Agora RTC SDK (auto-downloaded from SPM distribution on macOS)
- Rust Server: Axum, Tokio
Astation reads Agora credentials on first launch. Credentials are stored encrypted at ~/Library/Application Support/Astation/credentials.enc using AES-GCM with a key derived from the machine's hardware UUID.
# Build and run core tests
cd build && cmake .. -DBUILD_TESTING=ON && make && ctest --output-on-failure
# Build Swift app
swift build
# Run
swift run astation- Atem -- A terminal that connects people, Agora platform, and AI agents
- Chisel -- Dev panel for visual annotation and UI editing by anyone, including AI agents
- Vox -- AI latency evaluation platform
MIT