DEAD AIR
A first-person cave-horror game for the terminal. You are a search-and-rescue officer going into a half-mapped sink in Piney Ridge National Park after a solo caver who is nineteen hours overdue.
It opens above ground. You have one evening of light to walk the approach, read the ground, and talk to the people who saw Wren Alcott last — and then you go down the hole.
Every room draws itself — there are no image files. Each scene is calculated live, as if a camera really were standing in the cave, and lit by your actual lamp, so the picture loses reach and detail as the battery dies, for the same reason the prose does.
Built with Textual, so it runs anywhere Python 3.12 does — Linux, macOS and Windows, in a local terminal, over SSH, or inside tmux.
Every room is drawn to whatever the terminal can manage. The kitty graphics protocol gives the sharpest picture — kitty, Ghostty, WezTerm and Konsole speak it; terminals with sixel get that instead; everything else falls back to Unicode half-blocks, which is just text and works everywhere, including the plain Windows command prompt. It looks best in a terminal that can draw and it plays fine in one that can't.
Install
Needs Python 3.12 or newer. pipx is the tidiest way —
it keeps the game and its dependencies in their own environment and puts
deadair on your PATH:
pipx install deadair
Or with plain pip, ideally into a virtualenv:
pip install deadair
Either one also takes git+https://github.com/AustinGuidry/dead-air in
place of deadair if you want whatever is on GitHub right now rather than
the latest release.
Then, from anywhere:
deadair
Pass --seed N to fix the run's coin-flips — the same seed always gives you
the same cave noises. --help lists the options.
Updating
PyPI does not push updates — you pick them up when you ask for them:
pipx upgrade deadair # or: pipx upgrade-all
pip install --upgrade deadair # if you used plain pip
Once a day, on startup, the game quietly asks PyPI whether there is a newer
release and caches the answer; if you are behind, the menu says so and tells
you the command. The check runs on a background thread, times out fast, and
fails silently when you are offline. Set DEADAIR_NO_UPDATE_CHECK to any
value to turn it off. Running from a clone never checks.
Running from a clone
If you would rather have the source to hand:
git clone https://github.com/AustinGuidry/dead-air
cd dead-air
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
./play
Controls
| key | action |
|---|---|
1–9 |
take the numbered action — someone to talk to, something to look at, or a way on |
L |
listen |
R |
radio basecamp |
X |
look again |
F |
switch the helmet lamp on or off |
D |
stop the beam down — half the burn rate, half the sight |
C |
swap in a spare battery |
N |
new run |
Q / ESC |
back to the menu (which has new run and quit) |
F is for above ground — you start in daylight with the lamp off, and the
evening does not wait for you. D and C are underground only, where the
lamp is not something you get to switch off.
Saving
The game opens on a menu — resume, new run, controls, quit — and saves itself after every action, so quitting and closing the terminal are the same thing as putting it down. There is one slot and it is the run you are in. Finishing a run, however it finishes, clears it.
The file goes wherever your machine keeps application state: on Linux
~/.local/state/deadair/save.json, on macOS ~/Library/Application Support/deadair/save.json, on Windows %LOCALAPPDATA%\deadair\save.json.
Setting XDG_STATE_HOME overrides all three. Deleting the file is a supported
way to start over.
Take your time on the ridge. It teaches you what the cave will want before the cave asks you for anything.
You cannot see everything in the park before the light goes, and that is the point of the park.
Design notes
Mechanics, escalation, module layout, and tuning constants are documented in DESIGN.md — that file spoils the game, so read it only if you are here to work on the code rather than to play.
RELEASING.md covers cutting a version. It does not spoil anything.
License
MIT — see LICENSE.
Metadata
Release files for deadair 2.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| deadair-2.2.0.tar.gz | 138.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| deadair-2.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 274.0 kB
Release files / deadair-2.2.0.tar.gz
| Download URL | deadair-2.2.0.tar.gz |
|---|---|
| Size | 138.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fa078c5a6383e77f0bbd33940254120614edf8972c012fda0c36020dbb7275b3
|
|
BLAKE2b-256 checksum How to use checksums |
b0552e16dac8a3395472aba4453b7665d5aeb1e688b1642faab995372f0efe4e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.
Transparency logRelease files / deadair-2.2.0-py3-none-any.whl
| Download URL | deadair-2.2.0-py3-none-any.whl |
|---|---|
| Size | 135.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
da884b196c8ba5eae66346511f2c531916e7dbbb1d7589c12a808d78b74fe82a
|
|
BLAKE2b-256 checksum How to use checksums |
006ef37c7d6ac6e95ae04737a3fa150096ee2515775e9abe0684c49675b3f4bd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.
Transparency log