Skip to content

Getting Started

Note

This mirrors the repository's own README.md and infra/README.md, which are the up-to-date source of truth for exact commands and flags. If anything here looks out of date, trust the repo.

Prerequisites

  • X-Plane 12.1.1+, with its built-in Web API on port 8086 (on by default). It can run on a different machine than xatc itself -- see Reach X-Plane below.
  • Python 3.14+ and uv -- the only supported version (ADR 0011).
  • An AWS account -- Amazon Transcribe and Polly in us-east-1, plus the AWS CLI v2. Voice is always on (ADR 0012): without working AWS credentials xatc still starts, but voice won't, and the panel says why -- see Voice.
  • Node.js 22+ and the AWS CDK CLI (npm install -g aws-cdk), only to deploy the voice infrastructure once.

Everything except the AWS account can be skipped for a quick look: --replay a recorded flight and type your transmissions in the panel instead of speaking them, with no X-Plane and no AWS at all -- see step 5 below.

1. Install

uv sync                      # installs everything, including voice's dependencies
uv run pytest                # optional: check that everything passes

2. Deploy the voice infrastructure (one time)

This provisions two things in your AWS account, from a small CDK app in infra/:

  • An Amazon Transcribe custom vocabulary (xatc-aviation-en-US) tuned for aviation phraseology -- the NATO phonetic alphabet, "niner", facility and position names, runway/taxiway callouts. See Voice for how xatc uses it.
  • An IAM managed policy scoped to exactly what the voice layer needs (polly:SynthesizeSpeech, transcribe:StartStreamTranscription, transcribe:GetVocabulary). It's not attached to anyone automatically -- attaching it to your own IAM user is a decision only you should make.
cd infra && uv sync
npx cdk bootstrap            # one time per AWS account and region
npx cdk deploy

cdk deploy prints the policy's ARN when it finishes. Attach it yourself:

aws iam attach-user-policy --user-name <your-iam-user> --policy-arn <VoicePolicyArn from the deploy output>

3. AWS credentials that stay fresh (one time)

Don't export short-lived keys into your shell -- keys from aws login or SSO expire after about 15 minutes, and push-to-talk then fails with "security token ... expired". Instead, add a profile that asks the AWS CLI for fresh credentials whenever they're needed:

printf '\n[profile xatc]\ncredential_process = aws configure export-credentials --profile default --format process\nregion = us-east-1\n' >> ~/.aws/config

Replace --profile default with whichever profile you sign in with, and check it with:

AWS_PROFILE=xatc aws sts get-caller-identity

If your shell already has AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY or AWS_SESSION_TOKEN exported, unset them first -- they take priority over the profile.

Day to day, you shouldn't need a terminal for this at all. The radio panel's AWS status pill reflects whether these credentials are actually working right now -- click it and it runs aws login for you right there, no profile to set up first -- see AWS sign-in and status. The aws login/CLI setup above is still there if you'd rather run it yourself from a terminal, or you're setting this up somewhere without a browser handy on the same machine.

4. Reach X-Plane

X-Plane's Web API only listens on its own machine. If X-Plane runs on a different computer than xatc, forward the port over SSH:

ssh -fN -L 8086:127.0.0.1:8086 <user>@<xplane-host>
curl http://localhost:8086/api/capabilities     # should return JSON

Wait until X-Plane has fully loaded the aircraft before starting xatc.

Running on Windows

For a real flight, xatc is meant to run on the same Windows PC as X-Plane (see ADR 0006 in the repository) -- no SSH tunnel needed at all, since it reads X-Plane's Web API and its own data files locally. The SSH-tunnel setup in step 4 above is a dev-only option, for developing or testing xatc from a different machine than the one running X-Plane.

One-time setup -- from PowerShell, in the repository root:

scripts\setup-windows.ps1

This installs uv if it isn't already on your PATH (printing the official install command rather than running it for you, so it never silently installs anything without you seeing it first), runs uv sync, and finishes by running xatc doctor -- see below.

Every time you fly, double-click scripts\xatc-run.cmd. It runs xatc with whatever arguments you give it -- none, for the normal double-click case. It doesn't set AWS_PROFILE for you: xatc resolves which AWS credentials to use on its own (an AWS_PROFILE env var already set wins, else Settings → Advanced's AWS profile if you've configured one, else the default credential chain) -- most pilots never need step 3 above at all, and can just sign in from the panel's AWS pill. With no arguments, xatc runs live from settings.json and opens the panel in its own native window automatically; configure the flight plan, voice and everything else from the Settings page there, not flags. Flags still work for a one-off override, e.g. from a terminal:

scripts\xatc-run.cmd run --live --dest KPDX --cruise 35000

xatc doctor

Checks that this machine is actually ready to fly, without guessing:

uv run xatc doctor              # add --check-aws for a live (free, read-only) API check

It reports the Python and uv versions (failing below Python 3.14, the only supported version -- ADR 0011), whether an X-Plane installation was found (and whether its apt.dat, atc.dat and CIFP data are actually there), whether X-Plane's Web API is reachable right now, whether AWS credentials resolve, whether the same microphone the live session would use is available and actually picking up sound, and where the settings file and the log file live -- each as a pass/warn/fail line with a fix hint, plus a summary count. --check-aws additionally makes one free, read-only call each to Transcribe, Polly and Bedrock (Nova Lite) to confirm the account actually has access, not just that credentials resolve.

xatc smoke --live

xatc doctor checks static setup; xatc smoke --live is the hands-on follow-up, run against a real, running X-Plane session (an aircraft actually loaded) to sanity-check the parts doctor can't:

uv run xatc smoke --live              # add --voice to also test the speaker path

It samples live AircraftState for a few seconds (printing every field, and flagging pressure_altitude_ft/indicated_altitude_ft by name if the sim build doesn't expose them), round-trips a COM1 standby frequency change and back, pulls one live weather reading, and watches X-Plane's raw sim/joystick/joystick_button_values dataref for a few seconds so you can confirm which button index your yoke or joystick actually reports -- the same dataref push-to-talk from hardware's default X-Plane source reads live, and useful alongside its xatc ptt-probe too. With --voice, it also sends one real phrase through Polly and the VHF radio effect to your actual speakers -- Polly and the effect chain only, no Transcribe or microphone involved. It also samples the TCAS target datarefs (--tcas-seconds, default 5.0), resolving each one by its exact name -- a missing dataref just reports as a WARN for that one check, never a FAIL for the whole run. Like xatc doctor, it prints a pass/warn/fail report and never builds an AtcEngine -- it's a connectivity and data-availability check, not a flight.

5. Run it

From the repository root, with no arguments:

AWS_PROFILE=xatc uv run xatc

This runs live from settings.json and opens the panel in its own native window automatically (--browser keeps it in a browser tab instead). The first time, that file is empty, so open the Settings page (the gear icon) and fill in the Flight, Voice and other tabs there -- everything saves as you go, so this is a one-time setup per machine.

The header should show X-Plane 12.x · connected. Hold the PTT button, or hold Space while the page has focus, to talk -- or use a real yoke or joystick button instead, straight from X-Plane by default on Windows or macOS (Voice tab's Learn PTT button; see Push-to-talk from hardware). If the panel doesn't respond after an update, hard-refresh it (Cmd+Shift+R). The first time you use push-to-talk, macOS asks for microphone permission for your terminal app.

Voice is always on (ADR 0012) -- there's nothing to turn on. If it can't actually start (AWS credentials not signed in or expired, no microphone), xatc still runs: the panel says why and PTT is disabled with that reason instead of erroring, and you can keep flying by typing into the panel's transmit box. See Voice for exactly what that looks like and how to recover.

Flags still work, for development or a one-off override without touching settings.json:

uv run xatc run --live \
  --callsign N547GA --aircraft-type GLF5 --dest KPDX --cruise 35000

Without X-Plane or AWS, replay a recorded taxi and type your transmissions instead of speaking them:

uv run xatc run --replay fixtures/flights/ksea_taxi_out.jsonl --weather-fixture south-flow \
  --callsign N547GA --aircraft-type GLF5 --dest KPDX --cruise 35000

Run uv run xatc run --help for every flag.

Demo script

A five-minute walkthrough of a real IFR clearance and taxi-out, at KSEA:

  1. ATIS -- put 118.00 on COM2 and listen to the looping broadcast: wind, altimeter, ceiling and visibility, active runway, and an information letter.
  2. Clearance -- put 128.00 on COM1 and say "Seattle Clearance, November five four seven Golf Alpha, IFR to Portland with information Alpha." Read the clearance back.
  3. Taxi -- put 121.70 on COM1 and say "Seattle Ground, Gulfstream five four seven Golf Alpha, ready to taxi with Alpha." Read the taxi instruction back.
  4. Wrong frequency -- transmit on a frequency nobody's listening on, and you get silence.

Development

uv run pytest                          # the full suite, including the MVP acceptance test
uv run xatc record --out flight.jsonl  # record a live X-Plane session as a replay fixture

CI runs the suite on Python 3.14 (the only supported version, ADR 0011) in one job -- voice's dependencies are ordinary dependencies now (ADR 0012), so there's no separate voice-extra job to run -- plus a Windows run on push to main, and it synthesizes the infra/ CDK app.

Every option is described in the Settings reference.