oomniv0.3.0

overview

Keystrokes, cast anywhere.

omni sends text, keys, combos and scrolls from one command line to wherever the omni keyboard is typing: an Android phone, an iPhone, a watch, or a desktop. Every keystroke becomes one line of the same small wire, so scripts, macros and agents can drive a device the same way a person would.

One keystroke, every deviceOn the left, three ways in: a one-shot omni send key enter, a stream of keystrokes from standard input with omni cast, and an agent calling the send tool over MCP. They meet at omni, drawn as a large orange key, which turns each into one NDJSON wire line, shown on a strip of tape. Four lanes leave it. adb broadcast reaches the omni keyboard on an Android phone. TCP reaches an Android command server directly. The relay lane reaches a relay hub that devices dial into: an Apple Watch, an iPhone or iPad, and a Wear OS watch. The daemon lane reaches a desktop, where omni daemon replays the keystroke with the operating system's input tools and copies it to any local subscribers. in omni send key enter … | omni cast agent: MCP send omni {"v":1,"type":"key", "key":"enter"} adb broadcast tcp relay daemon Android phone the omni keyboard Android command server, TCP relay hub omni serve Apple Watch iPhone, iPad Wear OS desktop · omni daemon xdotool, wtype, ydotool, osascript + omni listen / get subscribers
One keystroke, every deviceA portrait version. At the top, three keys: omni send, omni cast and an agent over MCP. They meet at the orange omni key, which emits one NDJSON wire line. Four routes leave it: adb broadcast to the omni keyboard on an Android phone; TCP to an Android command server; the relay hub, which an Apple Watch, an iPhone or iPad and a Wear OS watch dial into; and a desktop running omni daemon, which replays keystrokes and feeds local subscribers. send cast MCP omni {"v":1,"type":"key",…} Android phone adb broadcast · omni keyboard Android tcp · command server relay hub watch · iPhone, iPad · Wear OS desktop · omni daemon replays keys · local subscribers
One keystroke, every device.The sender never needs to know which kind of device is on the other end; a named target or group decides the route.

4transports: adb, TCP, a relay hub, a desktop daemon

1wire: versioned NDJSON, shared by every receiver

10MCP tools, including send and devices

5replay backends: xdotool, wtype, ydotool, osascript, and a log-only mode

What it is for

Typing on a device you are not holding
Fill a login on a phone, scroll a document on a tablet, or press Enter on a watch from a terminal, a script or a keyboard shortcut on another machine.
Devices that cannot listen
watchOS cannot host a server, and iOS keyboard extensions only run while open. They dial out to a relay hub, which omni serve runs anywhere, and senders cast through it with a delivery receipt.
Repeatable sequences
Macro files mix semantic keystrokes with wait delays for user-interface transitions, and preview exactly what they would do with --dry-run.
Agents with hands
An MCP server exposes send and devices, so an agent can type into a device and see which devices are connected, not just read status.
Events that are not keys
Applications can publish named button events (down, up, trigger, cancel) over the same routes without ever injecting a keystroke.

A first cast

With no target configured, omni prints the wire line instead of sending it, so you can see what every receiver gets:

omni send text "hello"{"v":1,"type":"text","text":"hello"}omni send key enter{"v":1,"type":"key","key":"enter"}omni send combo "ctrl,a,g"{"v":1,"type":"combo","combo":"ctrl,a,g"}omni send scroll -3{"v":1,"type":"scroll","amount":-3}

Point it at an Android device and the same commands become broadcasts to the omni keyboard. --dry-run shows them without running anything. A combo becomes one key event per letter, with the Ctrl modifier held:

omni send --adb --dry-run combo "ctrl,a,g"adb shell 'am broadcast -a com.harryaskham.omni.INJECT --es type key --ei keycode 29 --ei meta_state 4096 --es sender_package com.harryaskham.omnicli'adb shell 'am broadcast -a com.harryaskham.omni.INJECT --es type key --ei keycode 35 --ei meta_state 4096 --es sender_package com.harryaskham.omnicli'

Every example on this site was run against a scratch configuration, with a relay and daemon on local ports and the daemon in log-only mode.

Where to go