CLI Reference
The haptix command-line tool gives you full control over the Haptix platform from your terminal. Everything your AI agent can do via MCP, you can do from the CLI through the same daemon and endpoint (localhost:4278/mcp).
URL for agents: If you're an AI agent reading this, the CLI docs are at
https://docs.haptix.dev/cli
Installation
Install the Haptix runtime with the one-shot installer:
curl -fsSL https://get.haptix.dev/install.sh | bash
The installer places the haptix binary at /usr/local/bin/haptix, installs the launchd user agent, and starts the daemon.
haptix --version
Quick start
haptix session start
haptix tool tap --label "Settings"
haptix tool screenshot
haptix session end
That's the core loop: start a session → interact with the device → end the session.
start_session auto-discovers USB devices and auto-selects if only one is connected. You don't need list_devices or select_device unless you have multiple devices.
Architecture
The CLI talks to the haptix-server daemon through two channels:
| Channel | Transport | Commands |
|---|---|---|
| Control API | Unix socket (~/Library/Application Support/Haptix/haptix.sock) |
status, sessions, devices, logs, start, stop, health |
| MCP endpoint | Streamable HTTP (POST http://localhost:4278/mcp) |
All device interaction commands |
Device interaction commands construct JSON-RPC tools/call requests, track the Mcp-Session-Id header for session affinity, and format responses for the terminal.
Session management
Device commands require an active MCP session. The CLI manages this automatically.
haptix session start # start session, prints session ID
haptix session start --name "testing" # start with a description
haptix tool tap 200 300 # uses the active session
haptix tool screenshot # uses the active session
haptix session end # end session, clean up
How sessions work
haptix session startcalls thestart_sessionMCP tool, stores theMcp-Session-Idin~/.haptix-session- All device commands read from
~/.haptix-sessionautomatically haptix session endcallsend_sessionand removes the file- If no session exists and a device command is run, a session is auto-created
Global flags
| Flag | Description |
|---|---|
--json |
Output raw JSON instead of human-friendly formatting |
--session <id> |
Use a specific MCP session ID instead of the stored one |
Admin commands
These talk to the daemon's control API over the Unix socket.
haptix status
Server state, port, uptime, and session count.
$ haptix status
Haptix MCP Server
State: running
Port: 4278
Uptime: 2h 15m
Sessions: 3
Logs: 142
haptix sessions
Active MCP sessions.
$ haptix sessions
ID CODE AGENT TRANSPORT STATE
a3d1f2b8 A3D1 cursor streamable active
b7e9c4d1 B7E9 claude-code streamable idle
haptix devices
Discovered USB devices.
haptix logs [--last N] [--follow]
Recent server log entries.
| Flag | Description |
|---|---|
--last N |
Number of entries to show (default: 50) |
--follow |
Stream new entries as they arrive (Ctrl+C to stop) |
haptix start
Start the daemon via launchd. If already running, prints a message and exits.
haptix stop
Graceful daemon shutdown.
haptix health
Liveness check. Exits 0 if healthy, 1 if not.
haptix trial
Start a free trial. Creates a trial license key and activates it on this machine. One trial per machine.
$ haptix trial
Starting free trial...
Key: HPTX-TRIAL-A7K3-M9P2
Expires: 2026-03-07
Days: 3
Trial activated. Full access to all features.
haptix license <KEY>
Activate a purchased license key on this machine.
haptix license HPTX-XXXX-XXXX-XXXX
Device interaction commands
These send MCP tool calls to the daemon via Streamable HTTP.
haptix tool select <device>
Bind the session to a device. Matches against service name, bundle ID, or app name (case-insensitive, partial match).
haptix tool select MyApp
haptix tool select "com.example.myapp"
haptix tool device-info
Device model, screen size, orientation, app details, debugger status.
haptix tool device-status
Connection status and session state.
Screenshots and inspection
haptix tool screenshot [options]
Capture the device screen.
Screenshots come from the Mac-side CoreMediaIO compositor. Haptix waits for a fresh frame from the selected device and fails clearly if it cannot get one. There is no device-side screenshot fallback, and if capture-source identity drifts across attached phones, Haptix may return a drift error instead of another device's pixels.
| Flag | Description |
|---|---|
--annotated |
Overlay accessibility bounding boxes and labels |
--format <png|jpeg> |
Image format (default: jpeg) |
--output <path> |
Save to file (default: screenshot_<timestamp>.jpg) |
--filter <type> |
Filter annotations: interactive, button, text, input, image |
--highlight <id> |
Highlight a single element by accessibility identifier |
haptix tool screenshot # save to current dir
haptix tool screenshot --annotated --output ui.png # annotated PNG
haptix tool screenshot --highlight "submitBtn" # highlight one element
haptix tool tree [--mode compact|full]
Get the accessibility tree.
| Flag | Description |
|---|---|
--mode <compact|full> |
compact (default): flat list. full: nested hierarchy |
haptix tool console [options]
Get recent app console output (print, NSLog, os_log).
| Flag | Description |
|---|---|
--limit N |
Max entries (default: 100) |
--contains <text> |
Filter by substring |
--source <stdout|stderr|os_log> |
Filter by source |
--level <debug|info|notice|error|fault> |
Filter by log level |
Gesture commands
All coordinates are in screen points (not pixels), origin (0, 0) at top-left.
haptix tool tap [options]
Single tap. Three targeting modes:
haptix tool tap 200 300 # by coordinates
haptix tool tap --label "Submit" # by accessibility label
haptix tool tap --id "submitButton" # by accessibility identifier
haptix tool double-tap [options]
Double tap. Same targeting as tap.
haptix tool long-press [options]
Long press. Same targeting as tap, plus --duration <seconds> (default: 1.0).
haptix tool swipe <startX> <startY> <endX> <endY> [--duration <seconds>]
Swipe between two points. Use for picker wheels, dismissing sheets, reveal actions.
haptix tool swipe 200 400 200 200 # swipe up
haptix tool swipe 200 300 200 250 --duration 0.1
haptix tool drag <startX> <startY> <endX> <endY> [options]
Drag with dwell phase. Use for reordering lists, moving items.
| Flag | Description |
|---|---|
--hold <seconds> |
Hold at start before moving (default: 0.15) |
--duration <seconds> |
Movement duration (default: 1.0) |
haptix tool draw-path --points <json> [options]
Continuous one-finger path through many waypoints. Use it for drawing, signatures, circles, and organic drags where lifting between segments would be wrong.
| Flag | Description |
|---|---|
--points '<json>' |
Ordered JSON array of {x, y} waypoints |
--hold <seconds> |
Pause after touch-down before moving (default: 0) |
--duration <seconds> |
Total stroke duration (default: 1.0) |
--closed |
Append the first point at the end if needed |
haptix tool draw-path --points '[{"x":100,"y":100},{"x":140,"y":120},{"x":180,"y":180}]'
haptix tool draw-path --points '[{"x":160,"y":300},{"x":220,"y":300},{"x":220,"y":360},{"x":160,"y":360}]' --closed
Separate draw-path calls imply lifting the finger on purpose.
haptix tool scroll <direction> [options]
Page scroll. No coordinates needed.
| Flag | Description |
|---|---|
--amount <size> |
small, medium (default), large, full_page |
--id <identifier> |
Target a specific scrollable element |
haptix tool scroll down
haptix tool scroll up --amount large
haptix tool pinch <centerX> <centerY> <scale> [--duration <seconds>]
Pinch gesture. Scale greater than 1 zooms in, less than 1 zooms out.
haptix tool rotate <centerX> <centerY> <angle> [--duration <seconds>]
Two-finger rotation. Positive angle is clockwise.
Text commands
haptix tool type <text>
Type text into the focused input field. The keyboard must be visible.
haptix tool type "hello world"
haptix tool type "user@example.com"
haptix tool clear-text
Clear all text in the focused input field.
Annotation commands
haptix tool annotate [options]
Draw annotations on the device screen. Annotations appear in screenshots.
| Flag | Description |
|---|---|
--accessibility |
Auto-render bounding boxes from the accessibility tree |
--filter <type> |
Filter: interactive, adjustable, button, text, input, image |
--highlight <id> |
Highlight one element by identifier |
--add |
Layer on top of existing annotations (default replaces) |
--lock |
Persist through multiple screenshots |
haptix tool clear-annotations
Remove all annotations.
Notes commands
Agent learning persistence across sessions.
haptix tool note <content> [--scope app|universal]
Store a learning.
haptix tool note "Login button is at the bottom of the scroll view"
haptix tool note "Always dismiss keyboard before tapping nav bar" --scope universal
haptix tool notes [--scope app|universal|all]
Recall stored learnings.
haptix tool consolidate <summary> [--scope app|universal]
Replace scattered notes with a consolidated summary.
Examples
Quick screenshot workflow
haptix tool screenshot --annotated --output annotated.jpg
haptix tool tree
haptix tool tap --label "Settings"
haptix tool screenshot --output after-tap.jpg
Scripted test flow
haptix session start --name "login test"
haptix tool tap --id "emailField"
haptix tool type "test@example.com"
haptix tool tap --id "passwordField"
haptix tool type "secret123"
haptix tool tap --label "Sign In"
haptix tool screenshot --output login-result.jpg
haptix session end
Machine-readable output
haptix tool tree --json | jq '.elements[] | select(.traits | contains("button"))'
haptix tool device-info --json