A tiny macOS daemon that turns an 8BitDo Ultimate 2C Wired Controller into a remote for Codex.
Important
PROXY requires Android/DInput mode. Unplug the controller, hold B, reconnect it, then release B when the light is steady.
The daemon reconnects automatically if the controller is unplugged.
| Input | Action |
|---|---|
| L4 | Bring Codex forward |
| B, held | Hold to dictate |
| A | Send the current message |
| LT | Toggle realtime voice |
| LB | End realtime voice |
| R3 | Clear the focused Codex field |
Caution
R3 sends Command+A and Delete. Confirm that the Codex composer has focus before pressing it.
| Input | Action |
|---|---|
| X | Start a new task |
| Y | Start a new standalone task |
| L3 | Open the most recent pinned task |
| Plus | Pin the current task |
| Minus | Unpin the current task |
| Left stick up/down | Move through pinned tasks |
| D-pad up/down | Move through projects |
| Right stick up/down | Scroll the conversation |
Right-stick scrolling follows the pointer. Keep the pointer over the conversation.
| Input | Action |
|---|---|
| RB | Bring Chrome forward |
| R4 | Bring Slack forward |
| RT | Unmapped |
| Item | Location |
|---|---|
| Installed app | ~/Applications/PROXY.app |
| LaunchAgent | com.kadekillary.proxy |
| Standard log | ~/Library/Logs/proxy.log |
| Error log | ~/Library/Logs/proxy.error.log |
The LaunchAgent starts PROXY automatically.
Note
A rebuild changes the app's ad-hoc signature. After each rebuild, remove and re-add PROXY under System Settings → Privacy & Security → Accessibility.
Follow the logs while troubleshooting:
tail -f ~/Library/Logs/proxy.log ~/Library/Logs/proxy.error.logPROXY handles Control-C as a graceful shutdown and releases an active dictation shortcut before it exits.
Format, lint, test, and build the daemon:
cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test
cargo build --bin proxyMeasure the safe action primitives in a release build:
cargo run --release --bin action_benchThe benchmark switches between Codex and Chrome. It does not post keyboard or scroll events. When the daemon exits through Control-C, it also prints median, p95, p99, and maximum HID-loop and action timings.
flowchart LR
accTitle: PROXY controller input flow
accDescr: Raw controller reports become typed actions that operate macOS apps or navigate Codex state.
HID["8BitDo controller"] -->|"raw HID report"| Controller["controller"]
Controller -->|"controller state"| Mappings["mappings"]
Mappings -->|"typed action event"| Actions["actions"]
Actions --> MacOS["macOS events"]
MacOS --> Apps["Codex, Chrome, or Slack"]
Actions --> State["Codex state adapter"]
State --> Database[("Local Codex state")]
Actions --> Navigation["navigation"]
| Component | Responsibility |
|---|---|
controller |
Parse raw HID reports into controller state |
mappings |
Convert state transitions into typed action events |
actions |
Coordinate actions without owning platform or persistence details |
actions/macos |
Activate apps, emit keyboard and scroll events, and clean up held input |
actions/codex_state |
Discover and validate the newest local Codex state database |
actions/navigation |
Select tasks and projects with pure navigation logic |
Warning
Pin and navigation actions depend on private local Codex state. PROXY validates that state at startup and stops with a compatibility error if the schema has changed.