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:
- ATIS -- put 118.00 on COM2 and listen to the looping broadcast: wind, altimeter, ceiling and visibility, active runway, and an information letter.
- 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.
- 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.
- 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.