Skip to content

fix: detect and control Codex Micro over HID (v0.3.9)#92

Merged
DevVig merged 3 commits into
mainfrom
fix/bluetooth-micro-control
Jul 23, 2026
Merged

fix: detect and control Codex Micro over HID (v0.3.9)#92
DevVig merged 3 commits into
mainfrom
fix/bluetooth-micro-control

Conversation

@DevVig

@DevVig DevVig commented Jul 23, 2026

Copy link
Copy Markdown
Owner

What

Fixes the production Codex Micro detection/claim path and prepares v0.3.9:

  • discovers the vendor interface directly through macOS HID instead of the unreliable USB-only system_profiler probe
  • supports transport-aware USB-C and Bluetooth HID descriptors
  • refreshes hot-plug presence every two seconds without repeatedly retrying a stable failed claim
  • requests Input Monitoring from the signed Microbridge app on Claim/Retry
  • marks Connected only after a successful HID write
  • keeps the home card, Device settings, and native right-click menu aligned
  • hardens release install/uninstall app replacement waits and staging cleanup

Bluetooth control is conditional on the paired device exposing the vendor HID interface, matching the physical transport contract.

Why

A physical Codex Micro was visible in macOS IOHID with VID 0x303A, PID 0x8360, and usage page 0xFF00, but Microbridge fell back to mock because system_profiler missed it. The previous claim path could also report Connected after opening a handle even when macOS rejected writes.

Validation

  • cargo test --workspace --all-targets — 85 passed
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo test --manifest-path apps/microbridge-ui/src-tauri/Cargo.toml — 11 passed
  • cargo clippy --manifest-path apps/microbridge-ui/src-tauri/Cargo.toml --all-targets -- -D warnings
  • pnpm --dir apps/microbridge-ui test — 35 passed
  • pnpm --dir apps/microbridge-ui build
  • bash -n scripts/install-from-release.sh scripts/uninstall.sh
  • CodeRabbit local review rerun — 0 findings
  • Developer ID–signed isolated app: detected codex-micro-usb; native right-click Claim changed the live snapshot to Connected; menu refreshed to Release; Release returned it to Detected
  • Signed bundle identity: ai.microbridge.ui, Team ID 3NQG568C4Q, hardened runtime, nested daemon/CLI signatures valid

Native QA boundary

USB-C claim/release is proven on the physical device. The paired Bluetooth device was still reported by macOS under device_not_connected during the run, so Bluetooth code/tests are green but final physical BLE claim proof remains pending an unplug/wake/connect cycle.

Summary by CodeRabbit

  • New Features

    • Improved hardware detection and control across USB-C and supported Bluetooth connections.
    • Added automatic Input Monitoring permission requests during device claiming and retry.
    • Added periodic device presence refresh without requiring app restarts.
    • Improved LED and connection status accuracy based on successful hardware communication.
  • Bug Fixes

    • Clarified claim, retry, release, and disconnected-device guidance.
    • Improved installation and uninstall handling when replacing or removing the app.
  • Documentation

    • Updated setup, troubleshooting, hardware, architecture, and release documentation.
  • Chores

    • Updated the release version to 0.3.9.

Copilot AI review requested due to automatic review settings July 23, 2026 01:00
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 15 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2794e8b2-8057-4f6c-bffd-553c7b0ec055

📥 Commits

Reviewing files that changed from the base of the PR and between a42013f and 0645c4f.

📒 Files selected for processing (9)
  • crates/mb-device/src/claim.rs
  • crates/mb-device/src/probe.rs
  • crates/microbridged/src/main.rs
  • crates/microbridged/src/state.rs
  • docs/device-hid.md
  • docs/hardware-bringup.md
  • docs/releases/v0.3.9.md
  • scripts/install-from-release.sh
  • scripts/uninstall.sh
📝 Walkthrough

Walkthrough

Microbridge 0.3.9 adds USB/Bluetooth HID transport detection, macOS Input Monitoring permission requests, periodic physical-device refresh, transport-aware hardware UI states, and updated installation, release, and troubleshooting documentation.

Changes

HID transport and hardware control

Layer / File(s) Summary
HID transport discovery and driver state
crates/mb-device/src/probe.rs, crates/mb-device/src/claim.rs, crates/mb-device/src/lib.rs
HID discovery now classifies USB, Bluetooth, and unknown transports; claimed devices expose transport-aware names and presence, and LED connectivity reflects successful writes.
Daemon presence refresh and LED lifecycle
crates/microbridged/src/main.rs, crates/microbridged/src/state.rs, docs/architecture.md
The daemon refreshes physical presence every two seconds, conditionally reclaims changed devices, resets LED rendering state, and emits device-change events.
Input Monitoring permission and control wiring
apps/microbridge-ui/src-tauri/src/lib.rs, apps/microbridge-ui/src/lib/hardwareControl.ts, apps/microbridge-ui/src/App.tsx
Tauri and UI paths request macOS Input Monitoring access before enabling hardware control.
Transport-aware UI states and validation
apps/microbridge-ui/src/components/DeviceEcho.tsx, apps/microbridge-ui/src/surfaces/*, apps/microbridge-ui/src/lib/*.test.ts, docs/device-hid.md, docs/design/README.md
Device detection, labels, claim guidance, and Bluetooth scenarios now use physical HID transport detection.
Release, installation, and hardware documentation
Cargo.toml, apps/*/package.json, INSTALL.md, docs/releases/*, scripts/*
Versions are bumped to 0.3.9, operational instructions are updated, and app installation/uninstallation waits for UI shutdown and cleans staging paths.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant MicrobridgeUI
  participant Tauri
  participant macOS
  participant Microbridged
  User->>MicrobridgeUI: Enable hardware control or choose Claim
  MicrobridgeUI->>Tauri: Request Input Monitoring access
  Tauri->>macOS: Check or request IOHID listen permission
  macOS-->>Tauri: Return permission status
  MicrobridgeUI->>Microbridged: Apply hardware-control configuration
  Microbridged->>Microbridged: Refresh HID presence and claim device
  Microbridged-->>MicrobridgeUI: Publish transport and connection state
Loading

Possibly related PRs

Suggested reviewers: copilot

Poem

A bunny found HID beneath the moon,
USB and Bluetooth hummed a tune.
“Ask permission, then claim with care,”
LEDs blinked through the midnight air.
Version nine hopped into view—
With tidy scripts and docs anew.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 65.45% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: Codex Micro detection and control over HID, with the release version noted.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates Microbridge’s Codex Micro hardware pipeline to detect devices via the macOS HID registry (instead of USB-only system_profiler), adds transport-aware naming for USB-C/Bluetooth, and tightens “Connected” semantics to require a successful HID write. It also prepares the v0.3.9 release across Rust/Tauri/JS packages and improves install/uninstall behavior for the signed macOS app.

Changes:

  • Add HID-registry-based presence probing with transport suffixes (-usb, -bluetooth) and refresh device presence every 2 seconds without repeatedly retrying a stable failed claim.
  • Request macOS Input Monitoring permission from the signed UI app on Claim/Retry paths, and only mark “Connected” after a successful HID write.
  • Release prep: bump versions to 0.3.9, update docs, and harden release app staging/cleanup during install/uninstall.

Reviewed changes

Copilot reviewed 29 out of 32 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
scripts/uninstall.sh Kill/wait for running UI before deleting the app bundle.
scripts/install-from-release.sh Track staging dir for cleanup; wait for UI exit before replacement.
INSTALL.md Uninstall steps updated; hardware control docs mention USB-C/Bluetooth.
docs/releases/v0.3.9.md New release notes for v0.3.9 hardware changes.
docs/hardware-bringup.md Update bring-up runbook for HID-registry detection + transport.
docs/governance.md Clarify upgrade flow includes microbridge-app install.
docs/device-hid.md Update HID presence/transport documentation and retry semantics.
docs/design/README.md Refine “Retry” copy to include permission-driven failures.
docs/architecture.md Update idle CPU budget explanation with HID presence refresh.
crates/microbridged/src/state.rs Add presence refresh API; render LEDs early; broadcast DeviceChanged after write-induced descriptor changes.
crates/microbridged/src/main.rs Schedule presence refresh on a 2-second cadence in the main loop.
crates/mb-device/src/probe.rs Prefer HID registry probe (hidapi) with transport reporting; keep USB fallback.
crates/mb-device/src/lib.rs Transport-aware device names; “Connected” only after successful write; rename “usb_present” to “device_present”.
crates/mb-device/src/claim.rs Track transport on claimed device using hidapi bus type.
Cargo.toml Workspace version bump to 0.3.9.
Cargo.lock Lockfile updates for 0.3.9 workspace crates.
apps/microbridge-ui/src/surfaces/surfaces.test.tsx Add UI test coverage for Bluetooth-detected copy.
apps/microbridge-ui/src/surfaces/Settings.tsx Use transport-aware physical-device detection/labels in settings text.
apps/microbridge-ui/src/surfaces/Popover.tsx Treat physical device presence beyond USB-only; update copy to mention Bluetooth.
apps/microbridge-ui/src/surfaces/Disconnected.tsx Improve disconnected guidance depending on current view.
apps/microbridge-ui/src/lib/hardwareControl.ts Add physical-device detection + transport labeling; invoke Input Monitoring request via Tauri.
apps/microbridge-ui/src/lib/hardwareControl.test.ts Add tests for transport labeling / physical device detection.
apps/microbridge-ui/src/components/DeviceEcho.tsx Display transport-aware “detected” status for physical devices.
apps/microbridge-ui/src/App.tsx Request Input Monitoring permission before enabling hardware control.
apps/microbridge-ui/src-tauri/tauri.conf.json Version bump to 0.3.9.
apps/microbridge-ui/src-tauri/src/lib.rs Implement request_input_monitoring_access command and use physical-device detection for menu actions.
apps/microbridge-ui/src-tauri/Cargo.toml Version bump to 0.3.9.
apps/microbridge-ui/src-tauri/Cargo.lock Lockfile updates for 0.3.9.
apps/microbridge-ui/package.json Version bump to 0.3.9.
apps/microbridge-ui/package-lock.json Version bump to 0.3.9.
adapters/sdk/package.json Version bump to 0.3.9.
adapters/claude/hooks/microbridge-permission.mjs Adapter metadata version bump to 0.3.9.
Files not reviewed (1)
  • apps/microbridge-ui/package-lock.json: Generated file

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread scripts/uninstall.sh
Comment thread scripts/install-from-release.sh
Comment thread docs/hardware-bringup.md Outdated
Comment thread crates/mb-device/src/probe.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/mb-device/src/claim.rs (1)

29-52: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Make HID selection deterministic when both transports are exposed.

  • crates/mb-device/src/claim.rs and crates/mb-device/src/probe.rs: both paths take the first matching HID entry, so a device exposed over USB and Bluetooth can flip the reported suffix and claimed interface across refreshes. Add an explicit transport tie-break instead of depending on HidApi iteration order.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/mb-device/src/claim.rs` around lines 29 - 52, The HID candidate
selection in claim.rs and probe.rs currently depends on HidApi iteration order,
causing inconsistent results when USB and Bluetooth entries both match. Update
the selection logic in both paths to apply an explicit, shared transport
tie-break before choosing the first candidate, while preserving preferred-PID
ordering and ensuring the same transport is selected consistently in
crates/mb-device/src/claim.rs lines 29-52 and crates/mb-device/src/probe.rs
lines 74-96.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/microbridged/src/main.rs`:
- Around line 89-102: The polling task currently holds the input_bus mutex while
refresh_device_presence performs potentially blocking HID enumeration.
Restructure the loop so poll_device_inputs and expire_leased_sessions retain
their locked path, but release the guard before probing; run
refresh_device_presence outside the mutex, then re-acquire input_bus only to
apply the resulting device-presence changes using the existing state APIs.

In `@docs/device-hid.md`:
- Around line 18-22: Update the device-presence documentation to state that
MockDevice is used only when no supported physical device is detected, while a
detected-but-unclaimed Micro remains represented as a HidDevice. Clarify that
this preserves the codex-micro-<transport> descriptor and Detected UI status,
distinct from Connected.

In `@docs/hardware-bringup.md`:
- Around line 21-27: Update the HID inspection command in the hardware bring-up
documentation to display the full matching IOHIDDevice record rather than
relying on the limited rg -A8 context. Preserve the existing matching criteria
and ensure VendorID, ProductID, and Transport are visible when validating the
pass condition.

In `@docs/releases/v0.3.9.md`:
- Around line 20-22: Update the release-note sentence describing the validated
physical Codex Micro claim/release path to explicitly state that it occurred
over USB-C, while preserving the remaining behavior and validation details.

In `@scripts/install-from-release.sh`:
- Around line 92-99: Treat an unconfirmed microbridge-ui shutdown as an error
before destructive operations: in scripts/install-from-release.sh lines 92-99,
recheck the process after the wait and abort or explicitly force termination
before replacing DEST; apply the same post-loop recheck and
abort-or-force-terminate behavior in scripts/uninstall.sh lines 43-49 before
deleting the app.

---

Outside diff comments:
In `@crates/mb-device/src/claim.rs`:
- Around line 29-52: The HID candidate selection in claim.rs and probe.rs
currently depends on HidApi iteration order, causing inconsistent results when
USB and Bluetooth entries both match. Update the selection logic in both paths
to apply an explicit, shared transport tie-break before choosing the first
candidate, while preserving preferred-PID ordering and ensuring the same
transport is selected consistently in crates/mb-device/src/claim.rs lines 29-52
and crates/mb-device/src/probe.rs lines 74-96.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a7fca421-d90d-4227-95f3-c2363e61e4ae

📥 Commits

Reviewing files that changed from the base of the PR and between 7771f67 and a42013f.

⛔ Files ignored due to path filters (3)
  • Cargo.lock is excluded by !**/*.lock
  • apps/microbridge-ui/package-lock.json is excluded by !**/package-lock.json
  • apps/microbridge-ui/src-tauri/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (29)
  • Cargo.toml
  • INSTALL.md
  • adapters/claude/hooks/microbridge-permission.mjs
  • adapters/sdk/package.json
  • apps/microbridge-ui/package.json
  • apps/microbridge-ui/src-tauri/Cargo.toml
  • apps/microbridge-ui/src-tauri/src/lib.rs
  • apps/microbridge-ui/src-tauri/tauri.conf.json
  • apps/microbridge-ui/src/App.tsx
  • apps/microbridge-ui/src/components/DeviceEcho.tsx
  • apps/microbridge-ui/src/lib/hardwareControl.test.ts
  • apps/microbridge-ui/src/lib/hardwareControl.ts
  • apps/microbridge-ui/src/surfaces/Disconnected.tsx
  • apps/microbridge-ui/src/surfaces/Popover.tsx
  • apps/microbridge-ui/src/surfaces/Settings.tsx
  • apps/microbridge-ui/src/surfaces/surfaces.test.tsx
  • crates/mb-device/src/claim.rs
  • crates/mb-device/src/lib.rs
  • crates/mb-device/src/probe.rs
  • crates/microbridged/src/main.rs
  • crates/microbridged/src/state.rs
  • docs/architecture.md
  • docs/design/README.md
  • docs/device-hid.md
  • docs/governance.md
  • docs/hardware-bringup.md
  • docs/releases/v0.3.9.md
  • scripts/install-from-release.sh
  • scripts/uninstall.sh

Comment thread crates/microbridged/src/main.rs
Comment thread docs/device-hid.md Outdated
Comment thread docs/hardware-bringup.md
Comment thread docs/releases/v0.3.9.md Outdated
Comment thread scripts/install-from-release.sh
@DevVig

DevVig commented Jul 23, 2026

Copy link
Copy Markdown
Owner Author

Addressed the outside-diff HID selection finding in 0645c4f: probe and claim now share one deterministic key that preserves preferred-PID priority, then prefers USB over Bluetooth over unknown when both transports are exposed. Added ordering tests, including preferred Bluetooth PID versus a different USB PID.

@DevVig
DevVig merged commit e642bf5 into main Jul 23, 2026
7 checks passed
@DevVig
DevVig deleted the fix/bluetooth-micro-control branch July 23, 2026 01:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants