Cross-platform virtual HID device library for AI agents
useHID lets AI agents control computers like humans do โ moving the mouse, typing on the keyboard, pressing gamepad buttons, taking screenshots, and reading UI elements. Built in Rust with bindings for Python, TypeScript, and Go.
from usehid import AgentHID
agent = AgentHID()
agent.execute({"action": "key_combo", "modifiers": ["cmd"], "key": "space"})
agent.execute({"action": "type", "text": "Google Chrome"})
agent.execute({"action": "key_press", "key": "enter"})- ๐ฑ๏ธ Virtual Mouse โ Move, click, double-click, drag, scroll
- โจ๏ธ Virtual Keyboard โ Type text, press keys, key combinations
- ๐ฎ Virtual Gamepad โ Joysticks, buttons, triggers
- ๐ธ Screenshot โ Capture full screen or regions as PNG
- ๐ณ UI Tree / Accessibility โ Read the OS accessibility tree (elements, roles, bounds)
- ๐ค Agent-Ready API โ Simple JSON interface for LLM agents
- ๐ฆ Pure Rust Core โ Safe, fast, zero-copy where possible
- ๐ Multi-language โ Python, TypeScript, Go bindings
The AgentHID class provides a JSON-based interface perfect for LLM tool-calling:
from usehid import AgentHID
agent = AgentHID()
# Query screen info
result = agent.execute({"action": "size"}) # Returns: {width: 1920, height: 1080}
result = agent.execute({"action": "position"}) # Returns: {x: 100, y: 200}
# Screenshot
result = agent.execute({"action": "screenshot"}) # Returns: {data: "<base64 PNG>"}
result = agent.execute({"action": "screenshot_region", "x": 0, "y": 0, "width": 400, "height": 300})
# UI Tree (Accessibility)
result = agent.execute({"action": "get_ui_tree", "depth": 3}) # Returns: {tree: {role, title, children, ...}}
result = agent.execute({"action": "find_ui_element", "role": "AXButton", "title": "Submit"})
# Mouse actions
agent.execute({"action": "mouse_move_to", "x": 500, "y": 300}) # Absolute move
agent.execute({"action": "mouse_move", "x": 100, "y": 50}) # Relative move
agent.execute({"action": "mouse_click", "button": "left"})
agent.execute({"action": "mouse_drag_to", "x": 600, "y": 400}) # Drag to position
agent.execute({"action": "mouse_scroll", "delta": -3})
# Keyboard actions
agent.execute({"action": "type", "text": "Hello, World!"})
agent.execute({"action": "key_press", "key": "enter"})
agent.execute({"action": "key_combo", "modifiers": ["ctrl", "shift"], "key": "s"})import usehid
# Screen info
width, height = usehid.size() # Get screen dimensions
x, y = usehid.position() # Get mouse position
usehid.move_to(500, 300) # Move mouse to absolute position
# Screenshot
png_bytes = usehid.screenshot() # Full screen โ PNG bytes
png_bytes = usehid.screenshot_region(0, 0, 800, 600) # Region โ PNG bytes
# Accessibility / UI Tree
tree = usehid.get_ui_tree(depth=3) # Returns dict with role, title, children, bounds...
elements = usehid.find_ui_element(role="AXButton") # Find matching elementsFor more control, use the device classes directly:
from usehid import Mouse, Keyboard
mouse = Mouse()
mouse.move_by(100, 50)
mouse.click("left")
mouse.drag(200, 100) # Drag by relative offset
mouse.scroll(-3)
keyboard = Keyboard()
keyboard.type_text("Hello!")
keyboard.combo(["cmd"], "s") # Cmd+S to save| Action | Parameters | Returns | Description |
|---|---|---|---|
size |
โ | width, height |
Get screen dimensions |
position |
โ | x, y |
Get current mouse position |
| Action | Parameters | Returns | Description |
|---|---|---|---|
screenshot |
โ | data (base64 PNG) |
Capture the full screen |
screenshot_region |
x, y, width, height |
data (base64 PNG) |
Capture a screen region |
Usage:
# Full screen
result = agent.execute({"action": "screenshot"})
png_base64 = result["data"]
# Region
result = agent.execute({"action": "screenshot_region", "x": 100, "y": 100, "width": 400, "height": 300})Platform backends: macOS (CGWindowListCreateImage), Linux (ImageMagick import), Windows (GDI BitBlt)
| Action | Parameters | Returns | Description |
|---|---|---|---|
get_ui_tree |
depth?, app? |
tree (UIElement) |
Get accessibility tree from focused/named window |
find_ui_element |
role?, title? |
elements (UIElement[]) |
Find matching elements in the focused window |
UIElement structure:
{
"role": "AXButton",
"title": "Submit",
"value": null,
"description": "Submit the form",
"bounds": {"x": 200, "y": 150, "width": 80, "height": 32},
"children": [],
"actions": ["AXPress"]
}Usage:
# Get full UI tree (depth-limited)
result = agent.execute({"action": "get_ui_tree", "depth": 3})
tree = result["tree"]
# Get UI tree for a specific app
result = agent.execute({"action": "get_ui_tree", "app": "Safari"})
# Find all buttons
result = agent.execute({"action": "find_ui_element", "role": "AXButton"})
buttons = result["elements"]
# Find element by title
result = agent.execute({"action": "find_ui_element", "title": "Save"})Platform backends: macOS (AXUIElement API), Linux (xdotool), Windows (UI Automation)
โ ๏ธ Requires Accessibility permissions on macOS (System Settings โ Privacy & Security โ Accessibility)
| Action | Parameters | Description |
|---|---|---|
mouse_move |
x, y, duration?, tween? |
Move by relative offset |
mouse_move_to |
x, y, duration?, tween? |
Move to absolute position |
mouse_click |
button? |
Click (left/right/middle) |
mouse_double_click |
button? |
Double click |
mouse_down |
button? |
Press and hold |
mouse_up |
button? |
Release |
mouse_scroll |
delta |
Scroll wheel (+up/-down) |
mouse_drag |
x, y, button?, duration?, tween? |
Drag by relative offset |
mouse_drag_to |
x, y, button?, duration?, tween? |
Drag to absolute position |
| Action | Parameters | Description |
|---|---|---|
type |
text, interval? |
Type a string (interval in ms) |
key_press |
key |
Press and release a key |
key_down |
key |
Press and hold |
key_up |
key |
Release |
key_combo |
modifiers[], key |
Key combination |
Supported modifiers: ctrl, shift, alt, cmd/meta/win
Supported keys: a-z, 0-9, enter, escape, backspace, tab, space, up, down, left, right, home, end, pageup, pagedown, delete, insert, f1-f12
For smooth movement animations, use the tween parameter:
| Tween | Description |
|---|---|
linear |
Constant speed (default if duration=0) |
ease_in / ease_in_quad |
Slow start |
ease_out / ease_out_quad |
Slow end |
ease_in_out / ease_in_out_quad |
Slow start and end (default) |
ease_in_cubic |
Cubic slow start |
ease_out_cubic |
Cubic slow end |
ease_in_out_cubic |
Cubic slow start and end |
ease_out_elastic |
Elastic bounce effect |
ease_out_bounce |
Bounce effect |
Emergency stop mechanism - moving mouse to any screen corner triggers failsafe and blocks further actions.
| Action | Returns | Description |
|---|---|---|
failsafe_status |
enabled, triggered |
Check failsafe state |
failsafe_enable |
โ | Enable failsafe (default) |
failsafe_disable |
โ | Disable failsafe |
failsafe_reset |
โ | Reset triggered state |
Usage:
# Check status
result = agent.execute({"action": "failsafe_status"})
# {success: true, enabled: true, triggered: false}
# If triggered, reset to continue
agent.execute({"action": "failsafe_reset"})
# Disable for specific operations (use with caution!)
agent.execute({"action": "failsafe_disable"})
# ... operations ...
agent.execute({"action": "failsafe_enable"})| Action | Parameters | Description |
|---|---|---|
gamepad_press |
button |
Press button |
gamepad_release |
button |
Release button |
gamepad_left_stick |
x, y |
Left stick (0-255) |
gamepad_right_stick |
x, y |
Right stick (0-255) |
gamepad_triggers |
left, right |
Triggers (0-255) |
Buttons: a, b, x, y, lb, rb, back, start, guide, left_stick, right_stick, dpad_up, dpad_down, dpad_left, dpad_right
| Platform | Mouse | Keyboard | Gamepad | Screenshot | UI Tree | Backend |
|---|---|---|---|---|---|---|
| macOS | โ | โ | โ | โ | CGEvent / CoreGraphics / AXUIElement | |
| Linux | โ | โ | โ | โ | uhid / ImageMagick / xdotool | |
| Windows | โ | โ | โ | โ | SendInput / GDI / UI Automation |
โ ๏ธ Gamepad notes:
- macOS: Requires code signing with
com.apple.developer.hid.virtual.deviceentitlement- Windows: Requires ViGEmBus driver
useHID requires Accessibility permissions for HID control and UI tree access:
- Go to System Settings โ Privacy & Security โ Accessibility
- Add your terminal app or the application using useHID
Screenshot capture works without Accessibility permissions. UI Tree / Accessibility features require the permission to read element attributes.
No special permissions required. Uses Win32 SendInput API for mouse and keyboard.
[dependencies]
usehid = "0.1"pip install usehidnpm install usehidgo get go.zoe.im/usehid@latestimport usehid "go.zoe.im/usehid"cargo run --release -p usehid --example agent_browseThis example demonstrates an AI agent:
- Opening Spotlight with
Cmd+Space - Typing "Google Chrome" and pressing Enter
- Opening a new tab with
Cmd+T - Navigating to github.com
- Scrolling the page
- Performing a search
cargo run --release -p usehid --example mousecargo run --release -p usehid --example keyboardcargo run --release -p usehid --example screenshotcargo run --release -p usehid --example ui_treeusehid/
โโโ usehid-core/ # Rust core library
โ โโโ src/
โ โ โโโ lib.rs # Public API
โ โ โโโ mouse.rs # Virtual mouse
โ โ โโโ keyboard.rs # Virtual keyboard
โ โ โโโ gamepad.rs # Virtual gamepad
โ โ โโโ screenshot.rs # Screenshot capture (PNG)
โ โ โโโ accessibility.rs # UI tree / accessibility API
โ โ โโโ agent.rs # JSON API for agents
โ โ โโโ screen.rs # Screen info & mouse position
โ โ โโโ failsafe.rs # Emergency stop mechanism
โ โ โโโ tween.rs # Smooth animation functions
โ โ โโโ hid.rs # HID report descriptors
โ โ โโโ platform/ # Platform backends
โ โ โโโ macos/ # CGEvent + IOHIDUserDevice
โ โ โโโ linux.rs # uhid
โ โ โโโ windows.rs
โ โโโ examples/
โโโ usehid-python/ # Python bindings (PyO3)
โโโ usehid-node/ # Node.js bindings (napi-rs)
โโโ usehid-go/ # Go bindings (CGO)
# Clone the repository
git clone https://github.com/jiusanzhou/usehid
cd usehid
# Build the core library
cargo build --release
# Run tests
cargo test
# Build Python bindings
cd usehid-python
maturin develop --releaseuseHID can be integrated with OpenClaw to give AI agents full control over your computer.
- Install useHID:
pip install usehid-
Grant Permissions (macOS): System Preferences โ Security & Privacy โ Privacy โ Accessibility
-
Copy the skill to OpenClaw:
cp -r skills/usehid ~/.openclaw/skills/- Use it:
You: Click the Chrome icon on the dock
OpenClaw: [executes mouse_click at dock position]
You: Type "github.com" and press enter
OpenClaw: [types text and presses enter]
You: Scroll down slowly
OpenClaw: [executes mouse_scroll multiple times]
| User Request | useHID Action |
|---|---|
| "Click here" | {"action": "mouse_click"} |
| "Type hello world" | {"action": "type", "text": "hello world"} |
| "Press Enter" | {"action": "key_press", "key": "enter"} |
| "Save the file" | {"action": "key_combo", "modifiers": ["cmd"], "key": "s"} |
| "Scroll down" | {"action": "mouse_scroll", "delta": -3} |
| "Take a screenshot" | {"action": "screenshot"} |
| "What's on screen?" | {"action": "get_ui_tree", "depth": 2} |
| "Find the Submit button" | {"action": "find_ui_element", "role": "AXButton", "title": "Submit"} |
| "Select all and copy" | Two actions: Cmd+A then Cmd+C |
See skills/usehid/SKILL.md for full documentation.
- AI Agents โ Let LLMs control desktop applications
- Browser Automation โ Alternative to browser-specific APIs
- Game Bots โ Gamepad simulation for testing
- Accessibility Tools โ Alternative input methods
- Testing โ Automated UI testing without browser dependencies
| Feature | useHID | PyAutoGUI | enigo | autopilot-rs | RobotGo |
|---|---|---|---|---|---|
| Agent-Ready JSON API | โ | โ | โ | โ | โ |
| Failsafe (Emergency Stop) | โ | โ | โ | โ | โ |
| Multi-language Bindings | Rust/Python/Node/Go | Python | Rust | Rust | Go |
| Gamepad Support | โ | โ | โ | โ | โ |
| Smooth Tween Animations | โ (10+ functions) | โ | โ | โ | โ |
| True HID-level Simulation | โ (Linux uhid) | โ | โ | โ | โ |
| Zero C Dependencies | โ (macOS/Windows) | โ | โ (libxdo) | โ | โ (CGO) |
| Screenshot | โ | โ | โ | โ | โ |
| UI Tree / Accessibility | โ | โ | โ | โ | โ |
| Image Recognition | โ | โ | โ | โ | โ (OpenCV) |
| Window Control | โ | โ (Win) | โ | โ | โ |
๐ค Built for AI Agents
# Other libraries: function calls
pyautogui.moveTo(100, 200)
pyautogui.click()
# useHID: JSON actions (perfect for LLM tool-calling)
agent.execute({"action": "mouse_move_to", "x": 100, "y": 200})
agent.execute({"action": "mouse_click"})๐ก๏ธ Safety First
- Built-in failsafe: move mouse to any screen corner to stop all automation
- Query and control failsafe state via API
- No accidental runaway scripts
๐ฎ Unique Gamepad Support
- Virtual gamepad for game automation and testing
- Full controller emulation: buttons, sticks, triggers
๐ True Multi-language
- Single Rust core with native bindings
- No subprocess spawning or IPC overhead
- Consistent API across Python, Node.js, and Go
โก Pure Rust Performance
- No C dependencies on macOS/Windows
- Memory-safe by design
- Fast and lightweight
| Library | Best For |
|---|---|
| PyAutoGUI | Screenshot + image recognition workflows |
| RobotGo | Go projects needing OpenCV integration |
| enigo | Rust projects needing Wayland support |
| autopilot-rs | Simple Rust automation with screenshots |
MIT License - see LICENSE for details.
- Inspired by foohid for macOS virtual HID
- Agent API design inspired by browser-use
Made with ๐ฆ by Zoe