An accessible, audio-first cross-country trucking simulation. Haul freight between more than 45 American cities, manage fuel, tolls, weather, and deadlines, and build a driving career entirely by ear.
Freight Fate is designed for blind and low-vision players first: every screen is fully voiced through your screen reader (NVDA, JAWS, SAPI, VoiceOver, Speech Dispatcher, and more via Prism), and the road speaks to you through a rich procedural soundscape. A simple visual display mirrors all speech for sighted players and helpers.
- Career mode — accept jobs inside metro freight markets, deadhead to specific origin facilities, deliver to specific receivers, earn money and experience, level up, and unlock cargo endorsements (refrigerated, heavy-haul, high-value).
- Realistic freight markets — the 59-city route graph acts as metro service areas, while each market expands into representative ports, rail and intermodal ramps, air cargo areas, parcel hubs, distribution centers, cold storage, food processors, farms/elevators, manufacturing plants, steel and automotive sites, chemical terminals, construction yards, mines/quarries, lumber/paper facilities, cross-docks, and company yards.
- Real driving — a tuned Class 8 truck simulation: 450 horsepower, ten gears (manual with clutch, or automatic), air-brake pressure, parking brakes, engine braking, grades, stalls, brake fade, and honest fuel economy.
- Trucks and upgrades — earn your way into a heavy hauler with more torque and a bigger tank (and worse aerodynamics), and outfit any truck with an engine tune, aerodynamic kit, long-range tank, or reinforced brakes. Every purchase changes the physics.
- A living market — each cargo class has a pay rate that drifts day by day, and each metro weights freight by regional specialization. The job board tells you when electronics are tight or bulk freight has gone loose; chase the tight markets.
- A living road — dynamic regional weather that changes grip and safe speeds, construction and traffic zones, road hazards that demand quick braking, curated rest stops and service plazas with parking certainty, carrier-paid toll-road settlement charges, and roadside rescue when you run dry.
- Real-world weather (optional) — flip Settings → Weather source to "real world" and each city uses its live current conditions from the free National Weather Service API. If it is raining in Chicago right now, it is raining in your game. Works without an API key and falls back to simulated weather offline. A separate calendar setting lets career dates and seasons keep advancing while live conditions remain enabled.
- Route planning — route options per job with distance, highways, state context, grade/terrain, toll events, curated POIs, and weather forecasts. Geometry coverage is broad, while generated placeholder POIs are reported as data gaps instead of dispatch-ready truck stops. Facilities add local pickup and delivery realism without pretending that every suburb or shipper needs a separate highway node.
- Original audio — sound effects and music are original project assets, with sources documented in the audio credits. Audio plays through BASS (via sound_lib), with the engine note pitch-tracking RPM in real time; pygame.mixer takes over automatically if BASS cannot initialize.
- Screen reader native — menus with first-letter navigation, contextual F1 help everywhere, on-demand information keys while driving, and three speech verbosity levels.
- Discord Rich Presence (optional) — when Discord is running, your profile can show what you are up to: in the main menu, at the terminal, driving a route, resting, or delivering, with the broad route and cargo. Only general game activity is shared — never your save files or personal details — and it is on by default but easily switched off in Settings → Gameplay → Discord presence. The game starts and runs perfectly whether or not Discord is open.
The easiest way to play is a prebuilt portable build from the releases page:
- Stable releases (
v1.6.0and so on) are the finished, numbered versions — pick the latest one. - Developer snapshots (
nightly-..., marked pre-release) are automatic nightly builds of work in progress: new features sooner, rough edges included. Heads up: a career saved on a developer snapshot may not load on an older stable release, so treat nightly saves as one-way.
Download the archive for your platform, extract it anywhere, and run the
game from the extracted FreightFate folder — FreightFate.exe on
Windows, FreightFate on macOS and Linux. There is nothing to install,
and the game is truly portable: your saves and settings live in a saves
folder inside the game folder, so you can move or copy the whole folder
(USB stick included) and your career travels with it. The game checks for
newer releases at the main menu and can download, install, and restart
itself — updates replace only the game's own files and never touch the
saves folder. Switch between stable and snapshot updates in Settings
under "Update channel".
On Linux there is also a single-file AppImage
(FreightFate-<version>-linux-x86_64.AppImage): mark it executable and run
it, no extraction needed, and it works beyond Ubuntu (Fedora, Arch,
openSUSE). Since an AppImage is read-only, its saves live in
~/.local/share/FreightFate. The in-game updater works here too — it
downloads the new AppImage, swaps the file in place, and restarts the game.
For a complete player-facing guide to installing, careers, dispatch, driving, route stops, saves, settings, audio, speech, and troubleshooting, see the Freight Fate Player Manual.
Want to help with code, docs, or world data? Start with CONTRIBUTING.md.
You need two tools installed and on your PATH:
-
uv — manages Python and all dependencies for you (it downloads a suitable Python automatically, so a system Python is not required). The official installer puts uv on your PATH for you; close and reopen the terminal afterwards so the change takes effect.
On Windows (PowerShell):
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
On macOS or Linux:
curl -LsSf https://astral.sh/uv/install.sh | sh -
git — required even after cloning, because one dependency (
sound_lib) installs straight from a git repository. Ifuv syncfails resolvingsound_lib, a missing git is almost always why.
git clone https://github.com/Orinks/Freight-fate.git
cd Freight-fate
uv sync
uv run freight-fateOn Linux you also need SDL and Speech Dispatcher packages from your
distribution (for example libsdl2-2.0-0 and speech-dispatcher on
Debian/Ubuntu).
tools/build_release.py produces the same portable build that the
releases page ships, using Nuitka. macOS uses Nuitka's app mode with
ad-hoc signing so Gatekeeper does not block the unsigned bundle on
downloaded builds:
uv sync --group build
uv run python tools/build_release.pyThis freezes the game into dist/FreightFate/, boots it once as a smoke
check, and archives it as dist/FreightFate-<version>-windows-portable.zip
(or -macos.zip / -linux-x64.tar.gz). Useful flags:
--skip-smoke— skip booting the frozen build (for cross-checking on headless machines).--tag <label>— override the version label in the archive name, as the nightly workflow does.
If the build succeeds but the archive seems to vanish on Windows, check
your antivirus: freshly built unsigned executables are sometimes
quarantined on sight. Add an exclusion for the dist/ folder or restore
the file from quarantine.
Freight Fate plays with the keyboard or a game controller, and both stay active at all times. Spoken prompts name whichever you last used, so "press X to take it" on the keyboard becomes "press D-pad down to take it" on a controller.
| Key | Action |
|---|---|
| Up / Down | Navigate |
| Enter | Select |
| Escape | Back |
| Home / End | First / last item |
| Any letter | Jump to the next item starting with it |
| F1 | Contextual help |
| Key | Action |
|---|---|
| Up arrow (hold) | Throttle |
| Down arrow (hold) | Brake |
| E | Start / stop engine |
| P | Release / set parking brake |
| Left Shift (hold) | Clutch (manual mode) |
| 1–0 | Gears 1–10 (manual mode) |
| N | Neutral (manual mode) |
| J | Engine brake toggle |
| H | Horn |
| X | Arm / cancel the next actionable exit |
| T | Refuel and rest (stopped at a rest stop) |
| Space | Speak speed, gear, RPM |
| Tab | Driving status menu |
| F | Fuel and range |
| C | Clock, deadline, ETA |
| R | Route progress |
| Shift+R | Next listed highway exit |
| L | Lane position |
| V | Weather and forecast |
| F1 | List all controls |
| Escape | Pause menu |
Plug in an Xbox, PlayStation, or other compatible controller and the game picks up the first one automatically. It detects a controller connected or unplugged mid-game — unplugging pauses the drive — and you can switch back to the keyboard at any time. Button names below use the Xbox layout; the equivalents map automatically on other pads. Turn controller support off under Settings → Gameplay → Controller if you prefer keyboard only.
| Button | Action |
|---|---|
| D-pad Up / Down | Navigate |
| D-pad Left / Right | Adjust the selected option (hold to repeat) |
| A | Select (like Enter) |
| B | Back (like Escape) |
| Back / Select | Contextual help (like F1) |
| Button | Action |
|---|---|
| Left stick | Steering |
| Right trigger | Throttle |
| Left trigger | Brake (press fully for the hardest stop) |
| Left bumper (LB) | Clutch (manual mode) |
| A | Shift up a gear (manual mode) |
| X | Shift down a gear (manual mode) |
| Y | Automatic speed control on / off |
| B | Speak speed, gear, RPM |
| D-pad Up | Route progress |
| D-pad Down | Take exit / signal a pull-over |
| D-pad Left | Weather and forecast |
| D-pad Right | Clock, deadline, hours of service |
| Left stick click (L3) | Horn |
| Right stick click (R3) | Engine brake toggle |
| Start | Pause / resume |
| Back / Select | Controller help |
Hold the right bumper (RB) as a modifier for a second layer of driving bindings:
| Button | Action |
|---|---|
| RB + A | Start / stop engine |
| RB + B | Fuel and range |
| RB + Y | Release / set parking brake |
| RB + D-pad Up | Next listed highway exit |
| RB + D-pad Down | Refuel and rest (stopped at a rest stop) |
| RB + D-pad Left / Right | Lower / raise the open-road cruise target |
| RB + Start | Driving status menu |
The left and right triggers are analog: hold them wherever you like for partial throttle or braking, rather than the ramped hold the arrow keys use. There is no controller emergency brake — press the left trigger all the way for the hardest stop.
Freight Fate models air pressure without asking players to run a full CDL
inspection before every dispatch. A cold trip starts with low pressure and
the parking brake set. Start the engine, wait for the compressor to build
air to 100 psi, then press P to release the parking brake. Repeated brake
applications draw from separate truck and trailer air tanks, low air warns
around 60 psi, and spring brakes apply around 40 psi. Normal driving should
feel familiar; the extra detail mostly gives clearer warnings if you pump the
brakes hard, ignore low air, or drive damaged equipment. Press Tab while
driving to review primary, secondary, and trailer air, compressor state,
parking or spring brake state, and brake heat.
The thresholds are grounded in official CDL and air-brake references: FMCSA describes typical 110-130 psi compressor cut-out, cut-in about 20 psi lower, and an 85-to-100 psi build-up check; the California DMV places low-air warnings between 55 and 75 psi; the Georgia DDS describes spring-brake and governor checks; and SGI lists 120-145 psi cut-out and 100 psi minimum cut-in. Build-up time is compressed for playability so startup is a short, understandable pause rather than minutes of waiting.
uv sync --group dev
uv run pre-commit install
uv run pre-commit install --hook-type pre-push
uv run pytest # full test suite, headless
uv run ruff check src tests toolsThe pre-commit hooks run Ruff lint fixes and formatting before commits. The
pre-push hook runs the release-note gate before publishing commits. It uses
tools.release_notes check --base auto --head HEAD, so user-facing changes need
a player-facing CHANGELOG.md entry unless the whole change set uses
changelog: none or [skip changelog].
The route tools edit the single src/freight_fate/data/world.json, but the game
loads the indexed src/freight_fate/data/world_data/ tree. After changing world
data, regenerate the index so the two stay in sync:
uv run python tools/index_world.py # rewrite world_data/ from world.json
uv run python tools/index_world.py --check # verify in sync (CI + pre-commit do this)A pre-commit hook and a test both fail if world_data/ drifts from world.json,
so commit the regenerated world_data/ files alongside your world.json edits.
Freight Fate is audio-first, so the way to review a playthrough is the transcript
of what the game says. tools/playtest.py drives the real game states headless
(no window, no speech) and prints that transcript:
uv run python tools/playtest.py # new-career delivery
uv run python tools/playtest.py --route "Newark->New York" # one corridor
uv run python tools/playtest.py --route "New York->Boston" --events-onlyUse --route to exercise a specific corridor after editing its route data. The
same harness backs the @pytest.mark.smoke delivery tests.
Player-facing changes should add a short bullet under ## Unreleased in
CHANGELOG.md. Developer snapshots use those curated entries for release
notes; they do not turn git commit subjects into player-facing copy.
Scheduled snapshots build only when new curated Unreleased entries are present,
or when a commit message includes nightly: build or [nightly build] for an
intentional snapshot refresh. Use changelog: none or [skip changelog] only
when every commit in the change set is non-user-facing.
Bundled audio assets ship as Ogg Vorbis files under
src/freight_fate/assets/sounds/ — see
CREDITS.md for provenance and
licensing.
Freight Fate is licensed under the PolyForm Noncommercial License 1.0.0: the source is public and free to use, modify, and share for any noncommercial purpose, but only the copyright holder may sell it or put it to commercial use. This is a source-available license, not an OSI-approved open-source license. Bundled audio credits and provenance are tracked in CREDITS.md.
BASS license caveat: audio playback uses the
BASS library (through the sound_lib Python
package), which is proprietary and free for non-commercial use only. If
Freight Fate is ever sold commercially (Steam, itch.io paid downloads, and
so on), a paid license must be purchased from
un4seen developments first.
The game falls back to pygame.mixer automatically when BASS is unavailable.