oomniv0.3.0

guide

Send, cast and script

Four ways to type through omni: one command at a time, a stream from standard input, a macro file with delays, or an agent over MCP. All of them reach the same targets.

Install

omni is a single Rust binary built with Nix. Add the flake as an input and install its package, or let a machine configuration do it:

inputs.omni-cli.url = "github:harryaskham/omni-cli";# packages.${system}.omni-cli provides bin/omni

Releases are tagged and built on self-hosted runners; an installed binary updates itself from them with omni update. To run omni as a service on a desktop or relay host, use the NixOS and nix-darwin modules.

omni statusomni v0.3.0update repo: harryaskham/omni-clifeedback:    true (stderr)

One command: send

omni send takes a command in the same words a macro uses: text, key, combo, scroll or event. Where it goes depends on the flags:

FlagsDelivers to
(none, no default target)Standard output, as one NDJSON line
--target NAMEA named target or group from the configuration (or its default_target)
--adb [--serial S]An Android device over adb, as a broadcast to the omni keyboard
--relay HOST:PORT --device IDA device connected to a relay hub (all devices if --device is omitted)
--daemon HOST:PORTA desktop running omni daemon
--dry-runNothing: prints the adb commands it would run
omni send text "hello"omni send --adb --serial emulator-5554 key enteromni send --relay hub:8765 --device quill --require-delivery text "hi"

With --require-delivery, a relay cast that reached no device exits with code 3, so a script can tell "device offline" apart from success.

A stream: cast

omni cast reads standard input and sends as it goes, keeping one connection open. Input is framed one of three ways:

--frameEachBecomes
line (default)linea text command
charcharacter, as typeda key or text command, in real time
ndjsonlinea wire command, passed through
echo "dictated paragraph" | omni cast --target phoneomni cast --frame char --daemon 127.0.0.1:8766         # type live into a desktop

Streaming casts do not wait for delivery receipts, to keep latency low.

Macros: run

A macro is a plain-text file of directives, one per line, run in order against the same targets as send. Each line is either a command (text, key, combo, scroll) or wait ms. Consecutive commands are dispatched together; only wait lines pause. Blank lines and # comments are ignored.

# a login: wait for the password field to appeartext quillkey tabwait 150combo ctrl,a,g
# with no target configured, a macro prints its wire linesomni run login.omni{"v":1,"type":"text","text":"quill"}{"v":1,"type":"key","key":"tab"}{"v":1,"type":"combo","combo":"ctrl,a,g"}omni run --dry-run login.omniadb shell 'am broadcast -a com.harryaskham.omni.INJECT --es type text --es text quill --es sender_package com.harryaskham.omnicli'adb shell 'am broadcast -a com.harryaskham.omni.INJECT --es type key --ei keycode 61 --ei meta_state 0 --es sender_package com.harryaskham.omnicli'wait 150msadb 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'

Without a target, a macro prints its wire lines, so omni run macro.omni | … composes with anything that reads NDJSON. - reads the macro from standard input.

Targets and groups

Connections are named in ~/.config/omni/config.yaml (or $OMNI_CONFIG, or --config). Each target is either one transport or a group of other targets, which casts to all of them.

default_target: phonetargets:  phone:    transport: { type: adb-broadcast, serial: emulator-5554 }  desk:    transport: { type: tcp, host: 127.0.0.1, port: 8766 }  tablet:    transport: { type: relay, url: tcp://hub.example:8765, device: quill, token_env: OMNI_RELAY_TOKEN }  everywhere:    group: [phone, desk, tablet]
omni config --target everywhereresolved --target everywhere -> 3 endpoint(s):  phone [adb-broadcast] adb device=emulator-5554 sender_package=com.harryaskham.omnicli  desk [tcp] tcp 127.0.0.1:8766  tablet [relay] relay tcp://hub.example:8765 device=quill

Relay tokens are never written in the file: token_env names the environment variable that holds one. omni config --example prints an annotated starter file, and omni config --schema its JSON Schema for editors. The reference lists every transport.

Health and completions

omni doctor runs read-only checks and prints one line per probe. It fails only on a real failure; warnings are advice.

omni doctoromni doctor — omni v0.3.0  [ok  ] binary: omni v0.3.0  [ok  ] config: 4 target(s) at ~/.config/omni/config.yaml  [warn] adb: not on PATH — `omni send --adb` needs the Android platform-tools `adb`  [ok  ] feedback: routing to stderr  [ok  ] update: self-update from harryaskham/omni-clihealthy (1 warning(s))

--probe adds bounded reachability checks (attached adb devices, and a 500 ms connection attempt to each TCP and relay target), and --json gives a structured report. For shell completion, omni completions bash|zsh|fish|powershell|elvish prints a static script; registering the dynamic completer also completes your target names after --target:

source <(COMPLETE=bash omni)