Plug in a USB device and instantly see what it is — USB version, negotiated speed, requested power, role and vendor — with live plug/unplug detection. Everything runs locally; nothing is uploaded.
Part of the UNI·SIM Universal Apps — free and open source (AGPL-3.0).
| Field | Source | Notes |
|---|---|---|
| USB 2 vs 3 / version | device descriptor bcdUSB |
reliable |
| Negotiated speed | libusb link speed | Low/Full/High = USB 2, SuperSpeed(+) = USB 3 |
| Role (HID / storage / hub…) | interface class codes | per-interface |
| Requested power | config descriptor bMaxPower |
what the device asks for (mA → W @ 5 V) |
| Data vs power-only | enumeration | anything that appears has working data lines; a charge-only cable never enumerates |
| Vendor / product / serial | string descriptors | best-effort — may be blank on Windows for class-driver devices |
| Charging / AC connected | OS power API (WMI + Electron powerMonitor) |
shown in a separate Charging & Power panel — a charger never enumerates on the USB bus |
| Charge rate (W into battery) | WMI root/wmi BatteryStatus |
Windows-only; not the charger's PD wattage |
| USB-C PD wattage (up to 240 W) | ❌ not in software | negotiated in the port controller / UCSI; needs an inline PD tester |
- Main area — things you plugged in since launch, plus any flash drive / disk (always), plus anything you've revealed.
- Built-in & already-connected (collapsed) — internal devices (Bluetooth, webcam…) and hubs. Each has a + reveal button to promote it to the main area; that choice persists across launches.
- Hidden (collapsed) — devices you've ✕-ed out of the main area, restorable with ↺.
- ✕ on a revealed device just sends it back to the background; ✕ on a genuinely-plugged-in device hides it.
"🔌 Test a cable" runs a guided, empirical check: it snapshots what's connected, asks you to plug a known device through the cable, and watches for a new enumeration. A device appearing proves the cable carries data + power; nothing appearing means it's charge-only, not a data device, or needs its own power. (Current rating / e-marker still needs a hardware tester.)
- Renderer (
src/) — React + Vite + Tailwind, fully sandboxed, no Node access. - Main process (
electron/main.cjs) — the only place with native access. Usesnode-usb(libusb) to enumerate devices, decode descriptors, and listen forattach/detach. Pushes plain device snapshots to the renderer over thepreload.cjsIPC bridge. web-demo/webusb-demo.html— a standalone WebUSB "try it" widget for the marketing/download page. Browser-only, per-device permission, identifies a device but can't read speed/power (that's the desktop app's pitch).
# Windows
cd D:/Github/UNISIM/Universal_Apps/Universal_USB
# macOS
cd /Users/jamesmarkey/Github/UNISIM/Universal_Apps/Universal_USB
npm install
# node-usb is a native module — build it against Electron's ABI if needed:
npm run rebuild
# Two terminals:
npm run dev # Vite dev server on http://localhost:5173
npm run electron:dev # Electron window pointed at the dev serverThe Claude Code preview server for this app is universal-usb on :5195 —
see Docs_UNI_SIM/dev-preview.md. It serves the same browser build as
npm run dev, so the USB banner below applies to it too.
Running
npm run devalone opens the app in a browser tab, where there is no USB bridge — you'll see the "desktop bridge isn't available" banner. USB access only exists inside the Electron window.
npm run dist:win # → release/electron-builder cannot produce macOS bundles on Windows — these must be run on a Mac. Both architectures are built, so Intel Macs get a native app rather than running under Rosetta.
npm run dist:mac # signed + notarised — needs the credentials below
npm run dist:mac:unsigned # no Apple account neededNotarisation is what stops macOS showing "can't be opened because Apple cannot check it for malicious software" — a dead end most people never get past, since the override is hidden behind right-click → Open. Two things are needed:
-
A "Developer ID Application" certificate in the login keychain. An "Apple Development" certificate is NOT enough — that one only provisions your own devices. Create the right one at developer.apple.com → Certificates → + → Developer ID Application (needs Account Holder or Admin on the team), then download and double-click it. Check with:
security find-identity -v -p codesigning
-
Notarisation credentials, read from the environment so nothing is ever committed:
export APPLE_ID="you@example.com" export APPLE_TEAM_ID="XXXXXXXXXX" export APPLE_APP_SPECIFIC_PASSWORD="abcd-efgh-ijkl-mnop"
The third is an app-specific password from appleid.apple.com → Sign-In and Security → App-Specific Passwords. Not your Apple ID password.
This is Developer ID distribution, not the Mac App Store, and deliberately so: the App Store requires the App Sandbox, which is built to prevent exactly what this app does — enumerate every connected USB device and open each one to read its descriptors.
dist:mac:unsigned needs no Apple account and produces working DMGs, but
anyone who downloads one hits the Gatekeeper block above. Fine for local builds
and testing; if you publish these, put the right-click → Open instruction next
to the download link.
Display name is Universal USB Detector; the folder / package / repo stay
universal-usb (uk.co.unisim.usb) for infra continuity.