Audio for Codex
Hear Codex's replies instead of reading them. Every reply OpenAI's Codex writes in VS Code is read aloud as soon
as it's finished, with each word highlighted as it's spoken, so you can look away from the screen while Codex works.
- Automatic: one click to connect to Codex, then every reply is read.
- Tells you when Codex needs you: "Codex needs your permission to run a command", so you can step away.
- Your choice of voice: your computer's built-in voices, or thousands of natural ElevenLabs voices, each with a
▶ sample. Speed from 1x to 3x, volume, and skipping code blocks.
- Sounds natural: file paths are read as file names, lists and headings as sentences, tables as lists, and links
as "link".
- Prompts tab: every prompt and reply in your latest Codex conversation, ready to hear again.
- Clipboard tab: text you copy or paste, read aloud on demand, with a daily archive.
- ElevenLabs usage in the status bar, so you always know how much of your plan is left.
- A button at the top right of the editor: a pause button while something is being read, then a repeat button.
Works on Windows, macOS and Linux. Requires OpenAI's Codex extension for VS Code, signed in with a ChatGPT plan that
includes Codex or an API key.
Unofficial: Audio for Codex is an independent extension for Codex. It isn't made by, affiliated with or
endorsed by OpenAI. OpenAI and Codex are trademarks of OpenAI; ElevenLabs is a trademark of ElevenLabs.
Getting started
- Install Audio for Codex. VS Code installs OpenAI's Codex extension along with it if you don't have it yet;
sign in to Codex if you haven't already.
- Audio for Codex asks once whether it may connect to Codex: choose Connect.
- Ask Codex something. The reply is read aloud as soon as it's finished, and the Audio for Codex panel (its icon
is in the left sidebar) shows each word as it's spoken.
- To also hear when Codex needs your permission, trust Audio for Codex's hook in Codex, once: in Codex's
Settings › Hooks, or with
/hooks in the Codex CLI (see How it connects).
- In the panel's Settings tab, pick a voice, speed and volume. For more natural voices, add an ElevenLabs API
key at the bottom of Settings (see Setting up an ElevenLabs API key).
What it needs
Audio for Codex needs OpenAI's Codex extension installed in VS Code and signed in, with a ChatGPT account or an API
key. It asks Codex itself (codex login status, with the program that comes with the Codex extension), again whenever
Codex's sign-in changes. If Codex isn't installed, Settings shows Codex is required with an Install Codex
button; if Codex isn't signed in, Settings shows Sign in to Codex. Either way the settings are locked until that's
sorted, and the message goes away by itself. If the sign-in can't be checked, nothing is blocked.
How it connects
Replies. Codex keeps a record of every conversation on your computer, a session file in
~/.codex/sessions (in the folder CODEX_HOME names, if you've set it). That's true whether you use Codex in VS Code
or the Codex CLI. Audio for Codex follows those files while VS Code is open, and reads each reply as soon as Codex has
finished it. Codex's working notes along the way aren't read, only the reply the turn ends with. Replies written while
VS Code was closed aren't read later. With several VS Code windows open, each reply is read once, by one window.
Subagents' own work isn't read; it comes back in the main reply. OpenAI notes that the session file format may change
between Codex releases; Audio for Codex reads it defensively.
Permission alerts. To say when Codex stops to ask before running a command or editing files, Audio for Codex adds
one PermissionRequest hook to Codex's hooks file, ~/.codex/hooks.json. Every other hook and setting in that file
is left exactly as it was, and a backup of the file as it was is kept next to it (hooks.json.bak). The hook only
speaks while Audio for Codex is running in VS Code, and it never answers the request, so Codex asks you as usual.
Codex only runs a hook once you've trusted it: open Codex's Settings › Hooks (or type /hooks in the Codex CLI)
and trust the hook that runs ~/.codex-audio/speak.ps1 (speak-mac.js on macOS, speak-linux.py on Linux). If
Codex's hooks are turned off (hooks = false under [features] in ~/.codex/config.toml), Audio for Codex says so;
replies are still read.
The first time Audio for Codex finds Codex it asks before adding the hook: Connect or Not now.
Not now works like Audio for Codex: Disconnect from Codex in the command palette (it removes the hook, and
replies aren't read): the choice is remembered (it won't connect by itself), and Settings shows Reading is turned
off with a Connect button. Audio for Codex: Connect to Codex does the same.
A new prompt stops the reading. Sending a prompt means you've moved on, so whatever is still being read stops
straight away. The next reply is read as usual.
Using Audio for Claude Code or Audio for GitHub Copilot as well? They can be installed side by side: Audio for
Codex keeps its files in ~/.codex-audio, and the commands of each are listed separately in the command palette.
The panel
Click the Audio for Codex icon in the left sidebar. The panel has four tabs (Prompts and Clipboard on the left, Shortcuts and Settings on the right):
- Shortcuts: Audio for Codex's three keyboard shortcuts and the keys they use now. Change opens VS Code's Keyboard
Shortcuts on that command: double-click it, press the keys you want, then Enter (right-click it there and choose
Reset Keybinding to go back to the default). The tab shows your own shortcuts as soon as they're saved, and
warns (in yellow) when a shortcut's keys are also used by another Audio for Codex shortcut or by another command, so one
of them wouldn't work; Audio for Codex also says so straight away when you save a clashing shortcut. (Audio for Claude
Code and Audio for GitHub Copilot use the same keys, so if more than one is installed, give them different keys here.)
- Settings: turn reading on or off, skip code blocks, change speed (1x to 3x) and volume, pick a voice (every voice in the list has a ▶
button that plays a short sample), and set up ElevenLabs.
- Prompts: the reply being read now, with the current word highlighted and a Stop button, and Recent
Prompts/Replies: every prompt in your latest Codex conversation for this VS Code window's folder (the latest 60),
newest first, each with Codex's reply, whether or not it was read aloud, with the conversation's first prompt as its
name above the list. It's read from Codex's own session file on your computer (without the context Codex adds
itself, such as AGENTS.md instructions), and new prompts and replies appear within a second. A prompt Codex is
still working on shows "No reply yet". Each card has ▶ (read again) and copy buttons, and shows the prompt and reply formatted the way the chat shows them (headings, bold, lists, tables, quotes and code blocks); click a reply or its prompt to show all of both.
VS Code doesn't tell other extensions which conversation is open in Codex, so the list shows the conversation used
most recently in this window's folder; start or continue one and the list follows it. With no folder open it shows
your latest Codex conversation anywhere. These cards have no remove button and there's no Clear all, since they
mirror the conversation itself.
The latest exchange is highlighted (blue left edge). To find an older prompt here, copy that prompt or reply in
Codex: the Prompts tab opens with that card highlighted and scrolled into view (copying part of a reply works too).
With Add copied text automatically on, the text also goes into the Read text aloud box.
Text copied this way isn't added to the clipboard history, and the highlight returns to the latest exchange with
your next prompt.
- Clipboard: text you copy while VS Code is in focus is added here automatically (it isn't read aloud by itself),
ready to listen to with ▶, and is also put in the Read text aloud box, ready to press Speak (not while you're
typing in that box). You can also paste or type any text there and press Speak (or Ctrl+Alt+Enter while typing in it). Select part of the text first to hear
just that part (the button then says Speak selection). Left out:
copies made in other apps; text that looks like a password, key or token (a long word mixing letters and digits,
KEY=value lines, user:password@host connection strings, private keys, and well-known token formats); and
anything copied while a secrets file such as .env, .pem, .key or secrets.json is the open editor. The
Add copied text automatically switch turns it off. VS Code has no clipboard-change event, so the clipboard
is checked once a second while VS Code is in focus.
Each day starts with an empty clipboard history: at midnight (or the next time VS Code starts) earlier days' texts
move to the Archive. Show archives (next to Clear all) switches the list to the archive, and Show
Recent switches back; the panel remembers which you were looking at. The archive has one folding section per day
(newest first, with the date and how many texts). Archived texts have the same ▶, copy and remove buttons,
Delete removes a whole day, and days older than 7 days are dropped. Clear all clears only today's list.
To hear just part of a card, select that text (in the prompt, the reply or a clipboard item) and press the card's ▶
(it turns blue while text is selected). The clipboard history is kept between VS Code sessions. When a new reply
starts being read, the panel switches to Prompts by itself (if the panel is closed, it opens there next time). Voice samples, pasted text
and replays don't switch tabs. Ctrl+Alt+S reads the text you've selected (in the editor, or in the panel), Ctrl+Alt+D stops
reading mid-sentence, and Ctrl+Alt+R reads the latest reply
again.
More natural voices (ElevenLabs)
The ElevenLabs card at the bottom of Settings asks Interested in more natural voices? and links to ElevenLabs
(free and paid plans). Need a key? Api key setup instructions, at the right of the ElevenLabs API key
label, shows step-by-step how to create one and which permissions to give it (Text to Speech: Access, Voices: Write,
User: Read). When you save a key, Audio for Codex also checks those permissions (without using any credits) and,
if any are missing, says which ones to change in ElevenLabs; fix them there and press Check again. It checks again
each time VS Code starts. Paste your ElevenLabs API key into the password box and press Save: Audio for Codex checks
it with ElevenLabs first, then keeps it in VS Code's secure storage (Windows Credential Manager, macOS Keychain or the
Linux secret service). The key is never written to a settings file, and the panel only ever shows its last four
characters. Once a valid key is saved, the card shows just the key, with Remove to delete it and an
ElevenLabs button that opens your ElevenLabs dashboard; removing it brings the invitation back. Once the key has
every permission Audio for Codex needs, Api key setup instructions is hidden too (it comes back if a permission goes
missing).
With a key saved, the Voice picker lists your ElevenLabs voices (the standard ElevenLabs voices plus any you've
added to your account) under the built-in ones. Each shows its accent, gender and style, a picture when ElevenLabs
provides one (otherwise an illustrated face that matches the voice's gender and age), and a ▶ button to hear ElevenLabs' sample. Search at the top of the list
filters voices.
Your ElevenLabs voices come in two groups: ElevenLabs · My Voices (voices you've cloned, designed or added from
the Voice Library) and ElevenLabs · Default voices (the standard ones every account has). Tick Show only "My
Voices" from ElevenLabs, at the right of the Voice heading (greyed out until a key is saved, as are the Language, Accent, Age, Voice Type and Style filters; Gender works for the built-in voices too), to list only your own
voices; the filters then offer only the languages, accents and styles your voices have, and the Voice Library is
hidden. The panel remembers the tick.
Below your own voices is ElevenLabs' Voice Library: over 10,000 voices shared by the ElevenLabs community.
Trending voices are shown first and more load as you scroll; the search box searches the whole library. Choosing
a library voice adds it to your ElevenLabs account ("My Voices") first, which needs the key's "Voices: write"
permission; library voices don't use up your custom voice slots. Some library voices cost more credits per
character, which the list shows (for example "2× credits"). Library voices need a paid ElevenLabs plan.
A filters card under the Voice heading has labelled dropdowns, each starting at Any, in two rows:
Language, Accent and Gender, then Age, Voice Type and Style. Voice Type picks Trending, Featured, or what the
voice is for (Characters & animation, Narration & story, Conversational, Social media, Advertisement, Entertainment & TV,
Educational). Style stays disabled on Any until a type is chosen, then lists the styles found among that type's voices
(such as Deep or Raspy).
ElevenLabs' licensed Iconic voices (such as Optimus Prime) aren't included: they're licensed per project with the
rights holder's approval and can't be used through the API. They filter your own voices and the whole Voice
Library (ElevenLabs does the filtering, so all 10,000+ voices are covered). Built-in voices follow the Language and
Gender filters, and are hidden while an accent or age filter is on, since they don't have those details.
The panel remembers your filters.
When an ElevenLabs voice is chosen, replies are read by Audio for Codex inside VS Code (which holds the key
securely): the reading script hands the reply over, Audio for Codex gets the speech from ElevenLabs (model
eleven_flash_v2_5, which is fast and uses half the credits of the larger models), plays it, and highlights every
word exactly. The first sentence or two are fetched on their own, so reading starts after a short wait while the
rest is fetched in the background. If VS Code isn't running, or ElevenLabs can't be used (no internet, credits used
up, key rejected), the built-in voice reads the reply (or the part not yet read) instead and Audio for Codex says why.
Audio players used: Windows' own media player (nothing to install), afplay on macOS, and paplay, aplay, mpv
or ffplay on Linux (install one of them).
Usage in the status bar. While an ElevenLabs key is saved, the status bar at the bottom of VS Code shows how much
of your plan's character allowance you've used this period, for example 41% · 12k/30k. Hover over it for the exact
figures, your plan and the reset date; click it to open your ElevenLabs subscription page. It turns yellow at 75% and
red at 90%, and updates a few seconds after each reply read with ElevenLabs (and every 15 minutes). It needs the
key's "User: read" permission; without it, the item shows a warning explaining that.
Setting up an ElevenLabs API key
You only need this for ElevenLabs voices; the built-in voices work without it. ElevenLabs has a free plan.
Sign in at elevenlabs.io/app/developers/api-keys (or choose
Developers near the bottom of the left-hand menu, then API Keys).
Click Create Key (or + Create API Key).
Give it a name you'll recognise, such as Audio for Codex.
Leave Restrict Key switched on, then set these permissions. Anything not listed can stay on No Access:
| Permission |
Set to |
What Audio for Codex uses it for |
| Text to Speech |
Access |
Reading replies aloud |
| Voices |
Write |
Listing your voices and adding Voice Library voices (Write includes Read) |
| User |
Read |
Showing your usage in the status bar (shown as Access on some accounts) |
Optional: set a Credit limit if you want to cap how much this key can use.
Click Create Key, then copy the key straight away (it starts with sk_). ElevenLabs shows it only once.
In VS Code, open the Audio for Codex panel's Settings tab, paste the key into the ElevenLabs API key box at
the bottom and press Save.
Audio for Codex checks the key with ElevenLabs before saving it (without using any credits). If a permission is missing, it
says which one; fix it in ElevenLabs and press Check again. Once everything is set, the setup instructions are
hidden from the panel.
Already have a key without these permissions? On the API Keys page, open the ⋯ menu beside it, choose
Edit, change the permissions and click Save Changes. You don't need to paste it into Audio for Codex again; just
press Check again.
Keeping your key safe: Audio for Codex stores it in VS Code's secure storage (Windows Credential Manager, macOS Keychain
or the Linux secret service), never in a file, and only ever shows its last four characters. Remove it at any time
with Remove; you can also delete or disable the key on the ElevenLabs API Keys page.
Now reading
While a reply is being read, the panel shows it with the current word highlighted. On Windows the speech
engine reports each word, so the highlight is exact; on macOS and Linux it follows the reading speed,
so it may drift slightly on long replies.
Speech used on each system
| System |
Speech |
Needs |
| Windows |
Windows built-in voices (PowerShell) |
nothing |
| macOS |
say (JavaScript for Automation) |
nothing |
| Linux |
espeak-ng, espeak or spd-say (Python) |
Python 3 and one of those speech engines |
Speech always runs in the background, so Codex is never held up while a reply is read.
The same reply is never read twice in a row.
Before reading, each reply is tidied for listening. With Skip code blocks when speaking on (the default), code is
simply left out: code blocks (including ~~~ blocks, blocks inside list items, a block showing Markdown with its own
code inside, and a block that's never closed) and bits of code full of symbols in a sentence aren't read at all, while
short ones such as npm test or init() are. With it off, the code is read out too. HTML tags are read by their name
(<p> is read as "p", </p> as "closing p"), and no angle brackets or other code symbols are ever sent to the voice,
so it can't trip over them. Links are read by their text and web addresses as "link", file paths as just the file
name (src/media/panel.html is read as "panel.html"), tables as lists, and each list item and heading as its own
sentence.
Using it in a dev container
When you open a folder in a dev container (or attach VS Code to a running container), Audio for Codex runs inside
the container, next to Codex. A container has no speakers of its own, so the speech is made but has nowhere to
play, and you hear nothing, with the built-in voices and with ElevenLabs alike. When Audio for Codex finds itself
in a container without sound, it says so once, and the Settings tab shows these instructions until sound works.
To pass your computer's sound into the container, add the lines for the computer Docker runs on to
.devcontainer/devcontainer.json (if it already has mounts, containerEnv or postCreateCommand, add to those),
then run Dev Containers: Rebuild Container from the command palette.
Windows (Docker Desktop):
"mounts": ["source=/run/desktop/mnt/host/wslg,target=/mnt/wslg,type=bind"],
"containerEnv": { "PULSE_SERVER": "unix:/mnt/wslg/PulseServer" },
"postCreateCommand": "sudo apt-get update && sudo apt-get install -y python3 espeak-ng pulseaudio-utils"
Linux:
"mounts": ["source=${localEnv:XDG_RUNTIME_DIR}/pulse/native,target=/tmp/pulse-native,type=bind"],
"containerEnv": { "PULSE_SERVER": "unix:/tmp/pulse-native" },
"postCreateCommand": "sudo apt-get update && sudo apt-get install -y python3 espeak-ng pulseaudio-utils"
macOS: Docker can't reach a Mac's speakers, so first start a sound server on the Mac (in Terminal):
brew install pulseaudio
pulseaudio --load=module-native-protocol-tcp --exit-idle-time=-1 --daemon
Then add:
"mounts": ["source=${localEnv:HOME}/.config/pulse/cookie,target=/tmp/pulse-cookie,type=bind,readonly"],
"containerEnv": { "PULSE_SERVER": "host.docker.internal", "PULSE_COOKIE": "/tmp/pulse-cookie" },
"postCreateCommand": "sudo apt-get update && sudo apt-get install -y python3 espeak-ng pulseaudio-utils"
The postCreateCommand line installs what speech needs in the container: Python 3, the espeak-ng voice and a sound
player (paplay, which plays ElevenLabs voices). It's written for Debian and Ubuntu images, which most dev containers
use; leave out sudo if the container runs as root, and on Alpine use apk add python3 espeak-ng pulseaudio-utils.
Started the container yourself with docker run? These are the same settings as options:
| Docker runs on |
Options |
| Windows |
-v /run/desktop/mnt/host/wslg:/mnt/wslg -e PULSE_SERVER=unix:/mnt/wslg/PulseServer |
| Linux |
-v $XDG_RUNTIME_DIR/pulse/native:/tmp/pulse-native -e PULSE_SERVER=unix:/tmp/pulse-native |
| macOS |
-v ~/.config/pulse/cookie:/tmp/pulse-cookie:ro -e PULSE_SERVER=host.docker.internal -e PULSE_COOKIE=/tmp/pulse-cookie |
- Windows: this uses the sound Windows gives to WSL, so Docker Desktop has to be on its WSL 2 engine (the
default). If the folder you opened is inside WSL, the mount's source is
/mnt/wslg instead of
/run/desktop/mnt/host/wslg.
- Linux: this works with PipeWire and with PulseAudio. PulseAudio turns away a container user that isn't your own
user (root, for example): also mount
~/.config/pulse/cookie and set PULSE_COOKIE to it, as in the macOS lines.
- To check, in a terminal in the container:
pactl info shows the sound server when it can be reached, and
espeak-ng "hello" should be heard.
- GitHub Codespaces: a codespace runs on GitHub's servers, which have no speakers, so replies can't be heard
there.
Commands and shortcuts
At the top right of the editor, next to Split Editor Right, Audio for Codex's logo opens its panel. While something is being
read it shows a pause sign: click it to stop. When it has finished it shows a repeat sign: click it to hear the same
text again.
On a Mac, Ctrl+Alt+Enter is Cmd+Option+Enter. Change the keys for Read Selected Text, Stop Speaking and Read Last Reply Again on the panel's Shortcuts tab.
| Command (Ctrl+Shift+P) |
Shortcut |
What it does |
| Audio for Codex: Read Selected Text |
Ctrl+Alt+S |
Reads the selected text (nothing selected: no sound) |
| Audio for Codex: Stop Speaking |
Ctrl+Alt+D |
Stops the reply being read |
| Audio for Codex: Turn Reading On/Off |
|
Mutes or unmutes reading |
| Audio for Codex: Read Last Reply Again |
Ctrl+Alt+R |
Reads the latest reply again |
| (Clipboard tab, while typing in the Read text aloud box) |
Ctrl+Alt+Enter |
Speaks the box, or just the highlighted part |
| Audio for Codex: Test Voice |
|
Reads a short sample in your chosen voice |
| Audio for Codex: Disconnect from Codex |
|
Stops reading replies and removes its hook from ~/.codex/hooks.json |
| Audio for Codex: Connect to Codex |
|
Reads replies again and adds the hook back |
Privacy and your data
- Stays on your computer: your settings, the reply list, clipboard history and archive. Your ElevenLabs API key
is kept in VS Code's secure storage and never written to a file.
- Read locally: Codex's session files in
~/.codex/sessions (to read replies and show your prompts), whether
Codex is signed in (codex login status; your sign-in itself is never read), and the clipboard, only while VS Code is in focus and Add copied text automatically is on. Text that
looks like a secret is never kept, and the clipboard archive keeps 7 days.
- Changed outside VS Code: only Audio for Codex's own hook in Codex's hooks file,
~/.codex/hooks.json (with a
backup of the file as it was, hooks.json.bak), and only after you choose Connect; plus its own folder,
~/.codex-audio.
- Sent to ElevenLabs, only if you use an ElevenLabs voice or key: the text being read aloud (to turn it into
speech), and requests for your voice list and usage. Nothing is sent anywhere when you use the built-in voices.
- No tracking: Audio for Codex has no analytics or telemetry.
- Affiliate link: the Try ElevenLabs button uses an ElevenLabs affiliate link. Signing up through it may earn
the developer a commission, at no extra cost to you.
Uninstalling
Uninstall Audio for Codex from VS Code's Extensions view. Everything it kept is deleted: the ElevenLabs API key,
the reply list, clipboard history and archive, the voice-picture cache and its other switches (all in VS Code's own
storage, which VS Code itself keeps after an uninstall), its reading scripts, voice settings and temporary audio in
~/.codex-audio, and its hook in ~/.codex/hooks.json (every other hook is left as it was).
It's caught two ways: while VS Code is open (within a few seconds, or as the extension is shut down), and by VS
Code's own uninstall step after a restart (which leaves a small codex-audio-uninstalled marker in ~/.codex-audio). If
anything was missed, the next install wipes it before it starts and removes the marker. Disabling, updating or simply
reinstalling the extension keeps everything.
Feedback and licence
Report an issue, in the Feedback section at the bottom of the panel's Settings tab, opens an email to the
developer (markusbotha@gmail.com) in your mail app, with your versions filled in; nothing is sent until you send it.
Report problems or suggest ideas at
github.com/BeastFromPretoriaEast/Audio-for-Codex-issues.
Audio for Codex is free to install and use, but it isn't open source: copying, changing or republishing it isn't allowed
without permission. See the licence for the details.