AI Commander 2026

August 9, 2026 · View on GitHub

A gag voice assistant for the Ubuntu desktop.

It listens to you — genuinely, with real speech recognition. It answers out loud in a confident synthetic voice. It fills the screen with a retro-futurist console that scrolls status lines, draws progress bars and chirps at you.

The console a second after launch: subsystem lamps, the boot log landing its
results, telemetry moving on the right

It does not do anything.

That is the entire joke. You say "Claude, fix the home internet", the room hears "ACKNOWLEDGED. RUNNING NETWORK DIAGNOSTIC SWEEP.", the console probes a gateway, resolves DNS, stalls a progress bar at 68% and chirps its way to UPSTREAM LINK RECALIBRATED — and nothing whatsoever happens. Played at full volume in front of someone who has never seen it, it reads as an alarmingly advanced piece of kit.

You talk to it by holding R — no wake word, because the key already said you were talking to it. --always-on brings back the original, which answers to "Claude".

Why it's funny

Seamless voice-to-action on the Linux desktop is still, in practice, not a solved problem. Films have depicted it as solved since 1968. AI Commander 2026 closes the gap by implementing the half that Hollywood actually shows: the acknowledgement.

What is real and what is not

LayerReal?
Microphone capture, push-to-talk on RReal
Speech recognition (transcript of what you said)Real
Intent classification — deciding which theatrical response fitsReal
The city on the map at bootReal — an IP lookup, and usually right
Spoken response, beeps, console readout, progress barsReal, and entirely cosmetic
Any effect on your computerNone. By design.

There is no execution path in this codebase. Not a disabled one, not a --dry-run flag — the module that would run a command does not exist, and the intent router maps a transcript straight to a performance script. Nothing can be misconfigured into actually launching Chrome.

There is exactly one shell-out in the package, and it is the voice: espeak-ng, invoked with a fixed argument list, with the text to speak written to its stdin so it can never be read as arguments. The only module that writes a file is the first-run setup wizard, which saves the settings and key it just asked you for and which nothing in the running console can reach. A test walks the syntax tree of every module and fails on anything else, with both allowances named explicitly so they cannot quietly grow.

Three things do leave the machine, all obvious but worth stating: what you said goes to your chosen speech-recognition provider while the talk key is down; with the default voice, the scripted lines it speaks go to Microsoft's TTS endpoint; and at boot it asks a keyless geolocation service where its own IP address is. --voice espeak-ng, a local faster-whisper model and [geo] enabled = false make the whole thing offline.

The look

Retro, and in a terminal — because a wall of scrolling monospace reads as "high-tech" to a bystander in a way that a window with buttons never will. The target is the Hollywood command centre, roughly 1979–1995: WarGames, MU-TH-UR from Alien, sonar consoles, NORAD big-boards.

  • Full-screen console, neon phosphor green on near-black (amber and war-room alternates)
  • Box-drawing borders, blocky uppercase headers, monospace everything
  • Character-by-character typewriter output with a blinking block cursor
  • Neon loading bars that stall convincingly at 68% before finishing
  • Subsystem lights that flick between OK / WORK / WARN
  • Telemetry that never stops moving, including at idle — buffer levels, link latency, a core temperature that means nothing
  • A biometric scan at boot: a beam of light crosses the screen, a wireframe face resolves behind it, and it lands on MATCH — <YOUR NAME> CONFIDENCE 99.4%
  • A world map at boot with a blinking marker on your actual city, under TRIANGULATING UPLINK … LOCKED

Sound does at least half the work. Beeps, sweeps and data-stutter are synthesised procedurally rather than sampled, so no two are identical, and the machine occasionally narrates itself unprompted into the silence.

The voice is a deep, slow neural one (edge-tts, en-GB-RyanNeural), because a bystander has to actually parse what the machine claims to be doing — the specificity of "PACKET LOSS WITHIN TOLERANCE" is most of the joke. espeak-ng is there for anyone who wants the 1983 formant-synth version, and takes over automatically when the network is not available.

Install

From a .deb

scripts/build-deb.sh
sudo dpkg -i dist/ai-commander-2026_*.deb
ai-commander --check

Self-contained: a bundled virtualenv under /opt, a launcher in /usr/bin, and a menu entry. Build notes and the interpreter-version constraint are in docs/packaging.md.

From source

Needs Python 3.11+ and uv.

sudo apt install espeak-ng    # the fallback voice

uv venv .venv
source .venv/bin/activate
uv pip install -e .

Speech recognition runs through a provider interface, so pick one — or none, and type at it instead:

uv pip install -e '.[openrouter]'  # OPENROUTER_API_KEY — recommended, any audio model
uv pip install -e '.[gemini]'      # GEMINI_API_KEY or GOOGLE_API_KEY
uv pip install -e '.[openai]'      # OPENAI_API_KEY
uv pip install -e '.[local]'       # faster-whisper — no key, no network, slower first run

OpenRouter is the default because one key reaches every audio-capable model, Gemini's included, so changing provider is changing a model string. Note that its provisioning keys look identical to inference keys and fail with 401 User not found, which reads like a dead key rather than the wrong kind — curl -H "Authorization: Bearer $KEY" https://openrouter.ai/api/v1/key tells you which one you are holding.

Then let it ask you for the key:

ai-commander --setup

It writes your choice to ~/.config/ai-commander/config.toml and the key to ~/.config/ai-commander/credentials, which is loaded into the environment at startup — an exported variable always wins, so nothing changes if you would rather keep the key in your shell profile. (If a stale export is shadowing a key you just saved, --check says so under key source.) The first plain ai-commander on a machine with nothing configured runs the same wizard, and ctrl+k reopens the same questions inside the running console, applied without a restart. --asr auto (the default) takes the first provider that has what it needs.

Check what you have:

ai-commander --check

Run

ai-commander                       # full-screen console, push-to-talk armed
ai-commander --demo                # perform every script in turn — start here
ai-commander --always-on           # listen continuously for the wake word instead
ai-commander --no-mic              # typed input only
ai-commander --theme amber         # phosphor (default), amber, warroom
ai-commander --script network.reset  # perform one script, then exit

The voice:

ai-commander --voice espeak-ng    # offline, and the original aesthetic
ai-commander --comms-filter       # neural voice, band-limited to a console speaker
ai-commander --no-voice           # beeps only

Run it maximised, on a large font, ideally on an external display. The gag scales with screen area.

Hold R and say "fix the home internet." Let go and it answers — releasing the key is the send, there is no confirm step.

Tapping space works too — tap to start, tap to stop — because a terminal cannot tell the program that a key came back up, so a hold is inferred from the keyboard's auto-repeat and both idioms end up meaning the same thing. No wake word is needed: pressing the key already said you were talking to it. Nothing is recorded, and nothing is sent anywhere, unless the key is down.

--always-on restores the original behaviour instead: the console listens continuously and answers to "Claude, fix the home internet."

KeyDoes
rHold to record a message — or tap to start, tap to stop
tabFocus the typing box (which takes r with it, so you can type it)
escapeLeave the box, giving the talk key back to the mic
ctrl+kSettings — provider, key, model, mic mode. Applied live
ctrl+tCycle theme
ctrl+gMute / unmute the microphone
ctrl+rPerform a random script
ctrl+sAbort the current performance
ctrl+cQuit

Making it say new things

Responses are TOML, not Python. A new gag is a [[script]] block with a list of keywords and a list of theatrical steps — beeps, spoken lines, log lines with results, subsystem lamps, and progress bars that stall.

[[script]]
id = "network.diagnose"
match = ["internet", "wifi", "packet loss"]

steps = [
  { sfx = "ack" },
  { say = "ACKNOWLEDGED. RUNNING NETWORK DIAGNOSTIC SWEEP." },
  { log = "PROBING GATEWAY", result = "OK", dots = true, delay = [0.4, 1.2] },
  { progress = "RECALIBRATING UPSTREAM", duration = [6, 11], stall_at = 0.68 },
  { sfx = "confirm" },
]

Full reference, including why every delay is a range and not a number: docs/performance-scripts.md.

Configuration

--setup writes the few settings it asks about. For anything else, copy ai_commander/data/config.toml to ~/.config/ai-commander/config.toml and change only the lines you care about — your file is layered over the defaults key by key. Worth knowing:

SettingDoes
[mic] modepush_to_talk (default) or always_on
[mic] ptt_keyThe talk key. r by default; space, f, ctrl+space all work
[mic] ptt_release_msRaise it if a held key keeps cutting itself off
[asr] providerauto, gemini, openrouter, openai, local, none
[geo] enabledfalse to boot without the map, and without the lookup
[biometric] identityThe name the face scan matches. Blank = your account name
[biometric] enabledfalse to skip the scan and boot faster

Status

Working. Boots, locates itself, listens, transcribes, classifies, performs. Real telemetry on the rail, procedural audio, seven domains of scripted response.

Packaged and tested as a .deb on Ubuntu / Python 3.14.

The silero VAD path is present but only lightly exercised, and it now matters less: it only runs in --always-on.

Licence

MIT.