Experimental, reversible compatibility patches for using the
OpenAI × Work Louder Codex Micro with the
codex-desktop-linux overlay on NixOS.
The tested desktop bundle already contains Linux-aware Codex Micro code, but three rollout and packaging gaps prevent it from loading:
- The Micro service/UI and composer dictation are behind remote feature gates.
- The Linux
node-hidbinary exists inapp.asar.unpacked, but is absent from theapp.asarindex. - The NixOS launcher’s library path omits
libusb-1.0.so.0.
This repository patches an existing local installation. It does not redistribute Codex, Work Louder software, firmware, or proprietary device-kit packages.
Warning
This is unofficial, version-sensitive software. Back up your overlay, review every script, and expect Codex updates to replace patched files.
There are two complementary Linux projects:
| Mode | Project | Use it when |
|---|---|---|
| Native Codex desktop | This repository | You want Codex’s built-in Micro layout, settings, RGB state, and push-to-talk |
| Standalone agent bridge | micro-herdr |
You want Micro keys/RGB mapped to herdr or arbitrary shell commands without depending on Codex desktop |
Both modes may try to own the same BLE/HID connection and RGB state. Do not run them concurrently unless you have independently verified multi-client behavior.
Before native Codex mode:
systemctl --user stop micro-herdr.serviceBefore micro-herdr mode, fully stop Codex desktop or restore the feature-gate
patch.
Currently supported and tested:
- NixOS on
x86_64-linux - Codex desktop app
26.715.72359 - Electron
42.3.0 codex-desktop-linux0.10.2 atefcf40b5ab41- Codex Micro over Bluetooth, VID:PID
303a:8360 - Work Louder Input
0.17.2 - Python
3.10+ asar3.2.4libusb1.0.29
Other app builds, architectures, and Linux packaging methods are unverified. The scripts reject unexpected gate counts and backup states instead of trying to patch a bundle they do not recognize.
git clone https://github.com/cartermccann/codex-micro-linux.git
cd codex-micro-linux
# Change this if your overlay lives elsewhere.
export CODEX_LINUX_OVERLAY="$HOME/projects/input-linux/codex-desktop-overlay"
python3 --version
test -x "$CODEX_LINUX_OVERLAY/electron"
test -f "$CODEX_LINUX_OVERLAY/resources/app.asar"The ASAR repair looks for asar on PATH, then searches realized Nix store
paths. Check either location:
command -v asar || ls /nix/store/*-asar-*/bin/asarThe HID runtime patch similarly locates an already-realized libusb. Realize
it if necessary:
ls /nix/store/*-libusb-*/lib/libusb-1.0.so.0 ||
nix build --no-link nixpkgs#libusb1Confirm the Micro works in Work Louder Input before patching Codex. For udev access checks and a narrowly scoped NixOS rule, see Troubleshooting → Device access.
Inspect current state:
python3 scripts/enable-codex-micro.py status
python3 scripts/repair-codex-native-modules.py status
python3 scripts/enable-codex-hid-runtime.py statusApply all three patches:
python3 scripts/enable-codex-micro.py enable
python3 scripts/repair-codex-native-modules.py repair
python3 scripts/enable-codex-hid-runtime.py enableEvery tool:
- creates an adjacent backup before changing material files;
- verifies the changed state;
- is idempotent;
- supports
statusandrestore; - accepts an explicit target-path argument.
If you prefer path arguments instead of CODEX_LINUX_OVERLAY:
scripts/enable-codex-micro.py --webview /path/to/content/webview
scripts/repair-codex-native-modules.py --resources /path/to/resources
scripts/enable-codex-hid-runtime.py --launcher /path/to/start.sh
Closing the window or reloading the renderer is insufficient. The Electron main process retains the previous ASAR header and native-module cache.
Use the launcher’s exact PID file, inspect the target, and terminate it:
pid_file="${XDG_STATE_HOME:-$HOME/.local/state}/codex-desktop/app.pid"
test -r "$pid_file" || {
echo "Codex PID file not found: $pid_file" >&2
exit 1
}
codex_pid="$(cat "$pid_file")"
codex_args="$(ps -p "$codex_pid" -o args=)" || {
echo "Codex PID is stale: $codex_pid" >&2
exit 1
}
case "$codex_args" in
*"$CODEX_LINUX_OVERLAY/electron"*) ;;
*)
echo "Refusing to terminate unexpected process: $codex_args" >&2
exit 1
;;
esac
printf 'Stopping PID %s: %s\n' "$codex_pid" "$codex_args"
kill -TERM -- "$codex_pid"Confirm no overlay process remains before reopening Codex:
pgrep -af "$CODEX_LINUX_OVERLAY/electron"That command should return nothing. After relaunch, it should show a different main-process PID.
The following layers are deliberately separate:
| Layer | Expected evidence | Project status |
|---|---|---|
| Feature activation | Micro and composer dictation gates report forced | Verified |
| Native packaging | ASAR contains the Linux entry with an unpacked payload | Verified |
| Dynamic linkage | HID_hidraw.node resolves libusb, libudev, and libstdc++ under launcher paths |
Verified |
| Device discovery | Fresh-process logs report successful Micro status RPCs | Verified |
| RGB control | Fresh-process logs report successful v.oai.rgbcfg RPCs |
Verified |
| Key actions | Agent/action keys trigger their intended behavior in Codex | Awaiting physical confirmation |
| Dictation | Hold/release Mic records, transcribes, and inserts text | Awaiting end-to-end confirmation |
Device discovery and RGB control were observed after a full Electron restart. Key actions and dictation remain deliberately unconfirmed. Please open an issue with sanitized logs when confirming a new working configuration.
The intended Mic behavior is:
- hold to record and release to transcribe;
- double-tap within roughly 350 ms to latch recording;
- tap again to stop latched recording.
The composer path is enabled. The unsupported Linux system-wide hold-to-dictate hotkey remains disabled intentionally.
| Tool | Local target | Backup |
|---|---|---|
scripts/enable-codex-micro.py |
Six Micro gate calls and one composer-dictation capability check | Adjacent *.before-codex-micro-linux files |
scripts/repair-codex-native-modules.py |
Rebuilds resources/app.asar with *.node files represented as unpacked entries |
app.asar.before-codex-micro-native and matching unpacked directory |
scripts/enable-codex-hid-runtime.py |
Prepends a realized Nix libusb directory to the launcher’s LD_LIBRARY_PATH |
start.sh.before-codex-micro-libusb |
No script downloads packages, edits firmware, modifies udev rules, or requires root.
First perform the same verified full-process shutdown described above. Then restore in reverse order:
python3 scripts/enable-codex-hid-runtime.py restore
python3 scripts/repair-codex-native-modules.py restore
python3 scripts/enable-codex-micro.py restoreVerify the original state:
python3 scripts/enable-codex-hid-runtime.py status
python3 scripts/repair-codex-native-modules.py status
python3 scripts/enable-codex-micro.py statusIf a tool reports a partial backup pair, stop and inspect it manually. Do not delete either member to make the warning disappear.
The tools use only the Python standard library:
make checkEquivalent commands:
python3 -m unittest discover -s tests -v
python3 -m py_compile scripts/*.py tests/*.pyAn offline Parakeet/sherpa-onnx pipeline can replace the transcription stage
if native Codex transcription proves unavailable on Linux. That integration
is not included here. A standalone push-to-talk binding belongs naturally in
micro-herdr; a native-Codex fallback should preserve the
official Micro press/release events and composer focus.
The original code in this repository is available under the MIT License. Upstream applications, device kits, firmware, and trademarks remain subject to their respective owners and licenses.