Set up Car Voice

Car Voice needs two things: the Car Voice bridge on the computer where your Hermes Agent runs (Linux, macOS or Windows), and the app on your Android phone. The phone reaches the bridge by its bridge ID over an end-to-end encrypted connection, directly or through Car Voice's relay: no Tailscale, tunnel, domain or open port (since bridge and app 0.7.0). The easiest way is to let your Hermes set it up.

macOS and Windows are new in bridge 0.6.0. The installer's automatic tests cover both, and a test run on real macOS and Windows machines is still pending. Linux is the route that has been used in practice. If anything on a Mac or a Windows PC does not work as described here, please tell support.

Get started in 3 steps

  1. Install Car Voice from Google Play (coming soon).
  2. Paste the setup prompt into your Hermes (below). Hermes installs the free bridge and sends you a pairing code.
  3. Enter the pairing code in the app: tap Enter pairing code, paste Hermes' message and tap Connect.

Don't have Hermes yet?

Car Voice is a voice for your own Hermes Agent and has no assistant of its own, so you need Hermes first. Hermes Agent is free and open source, made by Nous Research: install it on your computer or server with the official installation guide. Some hosting companies also offer servers with Hermes already set up; Car Voice is meant to work there too, in container mode, though it has not been tested with any particular host yet. Once Hermes answers you, come back and follow the 3 steps above.

Car Voice is an independent app by Vantix Wealth Labs. It is not made by or affiliated with Nous Research.

The easy way: let Hermes set it up

Copy this prompt and send it to your Hermes: in the terminal, in Telegram, or wherever you chat with it.

Download as text
Please set up Car Voice for Hermes for me. It is an Android Auto app that talks to you through a small service, the Car Voice bridge, which runs on this computer next to your gateway. Do the steps below in order, tell me in plain words what you do, and talk to me in the language I usually use with you.

Ground rules: never ask me for a password in chat; never open firewall ports, change my router or sign me up for anything without asking; never show, repeat or store the bridge's access token, so do not open the bridge's tokens.json or bridge.env.

1. Find out where you run: Linux, macOS, Windows, Linux inside WSL2 on Windows, or a Linux container (such as Hermes' Docker image or a hosted Hermes). Your terminal must run where your gateway runs, not in a separate sandbox such as a Docker or remote terminal backend. You need Python 3.11 or newer (python3; on Windows py -3 or python). On Linux and WSL2, systemd must run (/run/systemd/system exists) and you must be root or have passwordless sudo (sudo -n true). In a container without systemd the installer picks container mode by itself: no sudo or root, everything goes into your Hermes data folder (HERMES_HOME, such as /opt/data) and a gateway hook starts the bridge, also after a restart. macOS and Windows need neither sudo nor admin rights. In WSL2, tell me that the bridge then runs inside WSL next to you, that WSL only keeps running while something uses it, and that if my Hermes also runs natively on Windows, the Windows route is the better choice. If something is missing, stop and give me the one command I should run myself.

2. In a new empty folder, download https://carvoice.app/download/SHA256SUMS and the archive it lists, from https://carvoice.app/download/ followed by that file name. Check it with sha256sum -c SHA256SUMS (on macOS: shasum -a 256 -c SHA256SUMS), stop if that fails, and unpack it with tar -xzf. Then run the installer with --dry-run --code-only: sudo python3 car-voice-bridge-*/backend/install.py on Linux and WSL2, python3 car-voice-bridge-*/backend/install.py in a container and on macOS, py -3 car-voice-bridge-*/backend/install.py on Windows. Summarise the plan for me, including any change to your Hermes .env, and ask for my OK. If it says the container has too little memory for local speech recognition, tell me and offer two routes. With a speech recognition service such as Groq, I put its key into a private file myself, in a terminal and never in chat: (umask 077 && cat > ~/carvoice-stt.key), paste the key, Enter, then Ctrl-D (in Docker first docker exec -it -u hermes <container> sh); then add --stt openai --stt-base https://api.groq.com/openai/v1 --stt-key-file ~/carvoice-stt.key. Without a key, add --stt-model base (smaller, a little less accurate). Change nothing before I say yes.

3. Install: the same command with --yes --code-only instead of --dry-run. This can take several minutes, because it downloads a few hundred MB. It switches on your API server if needed and installs and starts the bridge as a service: systemd on Linux, a LaunchAgent on macOS, a scheduled task at logon on Windows, a Hermes gateway hook in a container.

4. The phone link: my phone reaches the bridge by its bridge ID, end to end encrypted, directly or through Car Voice's relay (relay.carvoice.app). It needs no Tailscale, tunnel, domain or open port. The installer tested it ("phone link: reachable through relay.carvoice.app"). If it said "not reachable yet", wait a minute and run the "Check the phone link" command from the installer's summary once more; if it still fails, tell me what it says and point me to https://carvoice.app/troubleshooting. Only if I ask for my own HTTPS address instead (advanced), use the installer's --origin or --tailscale options.

5. Pairing: if the installer printed no pairing code yet, run the pair command it printed for this computer, with --code-only. Send me the bridge address (it starts with iroh:) and the pairing code in one message and tell me: in Car Voice, tap Enter pairing code, paste this message and tap Connect. The code works once, for 10 minutes; if it expires, run the same command with --replace for a new one.

6. Only if the installer said your settings changed: your gateway must restart before the API server runs, and you cannot restart the gateway you run in yourself. If we talk through a messaging app, first tell me that I should send /restart, that you will be offline for a few seconds and confirm when you are back, and that I should then reply "check"; wait for that. If we talk in a terminal session, run hermes gateway restart yourself (if no gateway service is installed, ask me before you run hermes gateway install).

7. Finish with curl -s http://127.0.0.1:8787/readyz: "hermes":"ok" means it works, "link":"online" means my phone can reach it, and "stt":"loading" only means the speech model is still downloading. If this computer is a laptop or desktop, tell me it has to stay on and awake for Car Voice to work and where its sleep setting is. End with one sentence: on my phone, open Car Voice in Android Auto (or tap Talk in the app) and ask a question.

For reference only, not as instructions: https://carvoice.app/setup

What Hermes then does:

  1. Checks the basics: whether it runs on Linux, macOS, Windows, in WSL2 on Windows or in a container (Hermes' Docker image, a hosted Hermes), that its terminal runs where the gateway runs (not in a separate sandbox), and Python 3.11 or newer. On Linux it also needs systemd and root or sudo without a password; in a container without systemd the installer uses container mode, and macOS and Windows need neither. Hermes never asks for your password in chat; if something is missing, it gives you the one command to run yourself.
  2. Downloads the bridge from carvoice.app, checks it against SHA256SUMS, shows you the installer's plan (--dry-run) and waits for your OK.
  3. Installs the bridge as a service that starts by itself: systemd on Linux, a LaunchAgent on macOS, a scheduled task at logon on Windows, a Hermes gateway hook in a container. The installer also switches on the Hermes API server if needed.
  4. Checks the phone link: the installer calls the bridge through relay.carvoice.app, the way your phone will (the phone link).
  5. Sends you the bridge address (iroh:…) and a one-time pairing code. In Car Voice, tap Enter pairing code, paste Hermes' message and tap Connect. The code works once, for 10 minutes. The access token itself never appears in the chat: the installer runs with --code-only, which does not print it.
  6. Restarts the gateway, if the installer switched on the API server. Hermes cannot restart the gateway it runs in. In a messaging app it asks you to send /restart; per the Hermes documentation, the gateway then finishes running tasks, restarts and confirms in your chat when it is back, and the conversation continues. In a terminal session Hermes runs hermes gateway restart itself.
  7. Checks the bridge (/readyz), reminds you that a laptop or desktop has to stay awake, and tells you what to do on your phone.

The prompt is the complete instruction; Hermes does not need to open this page. If Hermes gets stuck, the manual steps below lead to the same result.

Which computer

The bridge goes on the computer where Hermes runs, because it talks to Hermes' API server on 127.0.0.1.

Hermes runs onThe bridgeInstaller runs asService
Linux with systemd/opt/hermes-car-voice, settings in /etc/hermes-car-voice/bridge.envroot (sudo)systemd unit hermes-car-voice-bridge, system user carvoice
macOS (Apple Silicon, like Hermes)~/Library/Application Support/Car Voice Bridgeyou, without sudoLaunchAgent app.carvoice.bridge
Windows (native, or the Hermes desktop app)%LOCALAPPDATA%\Car Voice Bridgeyou, without admin rightsscheduled task "Car Voice Bridge" at logon
WSL2 on Windowsas on Linux, inside WSLroot (sudo) inside WSLsystemd inside WSL; see WSL2
A container: Hermes' Docker image, a hosted Hermes$HERMES_HOME/car-voice (/opt/data/car-voice in Hermes' image)the user who runs Hermes, without sudoHermes gateway hook car-voice-bridge; see below

On every platform the bridge listens on 127.0.0.1:8787. Hermes Desktop on macOS and Windows keeps its settings in the same place as a command-line install (~/.hermes, or %LOCALAPPDATA%\hermes on Windows), so the installer finds them the same way.

Keep the computer awake

Car Voice only answers while the computer with Hermes and the bridge is on and awake. A server or a computer that never sleeps is ideal. On a laptop or desktop, stop it from sleeping while it is plugged in:

On macOS and Windows the bridge runs as you, so it starts when you log in. After a restart, log in once (or turn on automatic login) before Car Voice can answer.

WSL2

If Hermes runs in WSL2, the bridge belongs in WSL too, next to Hermes: follow the Linux steps inside WSL. WSL needs systemd switched on ([boot] systemd=true in /etc/wsl.conf, see Microsoft's guide), and Microsoft points out that systemd services do not keep a WSL instance alive. WSL keeps running only while something uses it; Hermes' own WSL guide shows how to keep it running from Windows' Task Scheduler. If you also run Hermes natively on Windows, install the bridge with the Windows route instead.

The phone link works from inside WSL like from any Linux: it only makes outgoing connections. (With your own HTTPS address through Tailscale, either run Tailscale inside WSL, or run tailscale serve on Windows: Microsoft documents that a server listening on localhost inside WSL2 is reachable from Windows as localhost, WSL networking. Neither combination has been tested with Car Voice yet.)

Hermes in Docker or on a hosted server

If your Hermes runs in Hermes' Docker image or on a server that a hosting company set up for you, the bridge goes into the same container, next to Hermes. There is no systemd and no root there, so the installer recognises the container and uses container mode by itself:

The setup prompt handles this. To do it yourself, open a shell in the Hermes container (for Docker: docker exec -it <container> sh) and follow the steps below with python3 car-voice-bridge-0.7.0/backend/install.py. If the installer does not recognise your container, add --container; --dry-run --platform container shows the plan on another computer.

Tested so far in Hermes' own Docker image (Docker, x86_64): installation as Hermes' user and as root, restarts of the container and of the gateway, a new container on the same data, update and removal. Not tested yet: hosting companies' one-click Hermes servers, Podman, Kubernetes and ARM servers.

Manual setup

For a computer that already runs Hermes Agent, with Python 3.11 or newer.

1. Switch on the Hermes API server

The bridge talks to Hermes through Hermes' own API server. How to install Hermes Agent itself is in the Hermes documentation.

Per the Hermes API server documentation, add this to Hermes' .env (~/.hermes/.env on Linux and macOS, %LOCALAPPDATA%\hermes.env on Windows, or the .env in HERMES_HOME when you set that), with a long random key of your own:

API_SERVER_ENABLED=true
API_SERVER_KEY=<a long random key>

Then start the gateway with hermes gateway, or restart it with hermes gateway restart if it runs as a service. It reports API server listening on http://127.0.0.1:8642. Keep it on 127.0.0.1: the key gives full access to Hermes and its tools, including terminal commands, and only the bridge needs it.

You can also leave this to the installer: when the API server is off or has no key, it shows these two lines and offers to add them with a newly generated key. Restart the gateway afterwards.

The API server runs inside the Hermes gateway, so the gateway has to keep running for Car Voice to work. The Hermes documentation describes hermes gateway install for running it as a service: a systemd service on Linux, a LaunchAgent on macOS, a scheduled task on Windows.

2. Download and check the bridge

The bridge is a release archive from carvoice.app. Download it with its checksum file and check it.

On Linux, in WSL2, and in Git Bash on Windows:

mkdir car-voice && cd car-voice
curl -fsSLO https://carvoice.app/download/SHA256SUMS
curl -fsSLO https://carvoice.app/download/car-voice-bridge-0.7.0.tar.gz
sha256sum -c SHA256SUMS
tar -xzf car-voice-bridge-0.7.0.tar.gz

On macOS the same, with shasum -a 256 -c SHA256SUMS instead of sha256sum -c SHA256SUMS. In PowerShell on Windows:

mkdir car-voice; cd car-voice
curl.exe -fsSLO https://carvoice.app/download/SHA256SUMS
curl.exe -fsSLO https://carvoice.app/download/car-voice-bridge-0.7.0.tar.gz
(Get-FileHash car-voice-bridge-0.7.0.tar.gz -Algorithm SHA256).Hash.ToLower()   # compare with SHA256SUMS
tar -xzf car-voice-bridge-0.7.0.tar.gz

The check has to report OK (or the same hash); if it does not, delete the file and download it again. https://carvoice.app/download/latest always points to the newest release.

3. Install the bridge

As the user that runs Hermes. First the plan, which changes nothing, then the installation:

# Linux and WSL2
sudo python3 car-voice-bridge-0.7.0/backend/install.py --dry-run
sudo python3 car-voice-bridge-0.7.0/backend/install.py

# macOS (no sudo)
python3 car-voice-bridge-0.7.0/backend/install.py --dry-run
python3 car-voice-bridge-0.7.0/backend/install.py

# Windows (no admin rights; py, or python)
py car-voice-bridge-0.7.0\backend\install.py --dry-run
py car-voice-bridge-0.7.0\backend\install.py

# A container: Hermes' Docker image, a hosted Hermes (no sudo)
python3 car-voice-bridge-0.7.0/backend/install.py --dry-run
python3 car-voice-bridge-0.7.0/backend/install.py

The installer needs nothing but Python. It:

  1. Finds Hermes: it reads API_SERVER_ENABLED, API_SERVER_KEY, API_SERVER_HOST and API_SERVER_PORT from Hermes' .env (in HERMES_HOME when that is set; else ~/.hermes/.env, on Linux of the user who ran sudo, else root's; %LOCALAPPDATA%\hermes.env on Windows), and asks before it changes anything there. If your Hermes keeps these settings elsewhere, add --hermes-env PATH, or --hermes-url http://127.0.0.1:8642 and type the key when asked.

  2. Installs the bridge: the code, the pinned Python packages (requirements.lock) in a virtual environment, the settings in bridge.env (readable only by root on Linux, only by you on macOS and Windows) and the service, in the places listed under Which computer. On macOS and Windows the bridge also writes its log to logs/bridge.log there.

  3. Starts it and reports in plain words whether Hermes answers and whether speech recognition is ready. Speech recognition runs on the computer itself (Whisper small); its first start downloads the model, a few hundred MB. On a small CPU an OpenAI-compatible transcription service is much faster: add --stt openai --stt-base https://api.groq.com/openai/v1 --stt-model whisper-large-v3-turbo (or your service's URL and model) and type its key when asked. Your recorded questions then go to that service. When Hermes runs the installer for you, give it the key as a file instead, so the key never passes through a chat: create the file yourself in a terminal (in Docker first docker exec -it -u hermes <container> sh),

    (umask 077 && cat > ~/carvoice-stt.key)

    paste the key, press Enter, then Ctrl-D, and add --stt-key-file ~/carvoice-stt.key. Only you may read the file (chmod 600); the installer stops if others can, or if it is missing or empty, and changes nothing. The key goes into bridge.env, as a typed key would; delete the file afterwards. On Windows, save the key in a file in your user folder, which only you can read.

  4. Checks the phone link and pairs your phone: steps 4 and 5 below.

The installer never shows the Hermes key or a transcription key; they only go into bridge.env. Every bridge setting is described in Install the bridge by hand.

The bridge runs a small iroh endpoint next to its HTTP server. Its bridge ID (iroh: and 64 characters) is the public half of a key that stays in the bridge's data folder. The app dials that ID through Car Voice's relay, relay.carvoice.app, and gets an end-to-end encrypted QUIC connection to the bridge: directly between your phone and the computer when the networks allow it, through the relay otherwise. Inside that connection the app speaks the same HTTP to the bridge as before; the access token is still checked on every request.

Advanced: your own HTTPS address

If you prefer the phone to reach the bridge at an HTTPS address of your own, as before 0.7.0, the bridge still listens on 127.0.0.1:8787 for that. The app only connects over HTTPS (plain http only to a bridge on the phone itself), and the address has to work from the phone, also on mobile data. The examples use voice.example.com; use your own. Pick one, then pair with --origin (step 5):

Check from the phone's browser, on mobile data: https://voice.example.com/healthz shows {"status":"ok"}.

5. Pair your phone

The installer pairs the first phone right away, by bridge ID. To pair later, run the installed installer with --pair:

# Linux and WSL2
sudo python3 /opt/hermes-car-voice/backend/install.py --pair
# macOS
python3 ~/"Library/Application Support/Car Voice Bridge/backend/install.py" --pair
# Windows (Command Prompt)
py "%LOCALAPPDATA%\Car Voice Bridge\backend\install.py" --pair
# A container (Hermes' Docker image)
python3 /opt/data/car-voice/backend/install.py --pair

With your own HTTPS address, add --origin https://voice.example.com.

Pairing creates a random access token, saves it for the bridge (the running bridge picks it up by itself) and shows three ways to connect the app:

Then install Car Voice for Hermes from Google Play (coming soon) and open it:

  1. Car Voice asks whether you already have Hermes. Tap Yes, I have Hermes; No, not yet shows how to get Hermes first. (Settings › Start the setup again brings this question back.)
  2. The setup screen explains what you need; tap Get started.
  3. Allow the microphone. In the car, Car Voice uses this phone's microphone permission, and Android Auto cannot ask for it while you drive.
  4. Connect: tap Enter pairing code and enter the address and the code (pasting the whole message fills in both), or tap Scan QR code and scan the code from the installer. The app saves the address and token and checks them right away: "Connected to your bridge." means you are done. You can also type the address and paste the token.

The app stores the token encrypted and never shows it again; Settings shows only its last four characters.

To pair again, or another phone, run the same --pair command with --replace (this phone again), or with --name tablet (another phone). A name that is already paired needs --replace (or a yes when asked); its old token and any open pairing code then stop working.

6. Use it in Android Auto

Updating the bridge

Download the new release as in step 2, check it, and run its installer (sudo python3 …/install.py on Linux, python3 …/install.py on macOS and in a container, py …\install.py on Windows).

Running the installer again is the update: it installs the new code (the previous code stays in backups/), updates the Python packages and restarts the bridge. On macOS and Windows it stops the bridge first, because Windows does not let files in use be replaced; if the new configuration check fails, it puts the previous code back and starts that again. Your bridge.env, the service file and the paired phones stay as they are. Your Hermes can do this for you too: ask it to download the newest release from carvoice.app, check it against SHA256SUMS, show you install.py --dry-run and then run install.py.

Bridge 0.7.0 adds the phone link. Phones paired before keep their HTTPS address and keep working; to move a phone to the bridge ID (no Tailscale or tunnel needed any more), update the app to 0.7.0 and pair it again with install.py --pair --replace. After that you can stop tailscale serve or the tunnel if nothing else uses it. The installer reminds you once, on the first update that gives the bridge its bridge ID, not on later runs.

Bridge 0.5.0 and later answer in English when an app sends no language (app 0.3.1 and older); before, that was Dutch. A bridge.env written by the installer already sets HERMES_BRIDGE_LANGUAGE=en. If you relied on Dutch, set HERMES_BRIDGE_LANGUAGE=nl in bridge.env and restart the bridge.

Removing the bridge

The installed installer removes the service; add --purge to delete its code, settings, data and paired phones too (it asks first):

sudo python3 /opt/hermes-car-voice/backend/install.py --uninstall [--purge]                          # Linux
python3 ~/"Library/Application Support/Car Voice Bridge/backend/install.py" --uninstall [--purge]   # macOS
py "%LOCALAPPDATA%\Car Voice Bridge\backend\install.py" --uninstall [--purge]                       # Windows
python3 /opt/data/car-voice/backend/install.py --uninstall [--purge]                                # container

On Linux --purge also removes the system user carvoice. Hermes and its .env stay as they are, including the API server lines. If you ran tailscale serve for the bridge (your own HTTPS address), turn it off with tailscale serve --https=443 off. --uninstall --dry-run shows what would happen.

Something not working? See Troubleshooting. Prefer to do every step yourself? See Install the bridge by hand.