← Onyx

Model Context Protocol

Agents get a way to reach you

An agent working in a terminal can do everything except get your attention. It finishes and you don't notice; it stops to ask something and you don't notice; it produces a result that would take one picture to explain and gives you four paragraphs instead. Onyx runs an MCP server so the agent can do the other half: interrupt you, reach your phone, and put a page on your screen.

It works from any machine you're connected to, not just your Mac. The connection Onyx already holds open for the terminal is the one the tools travel back on.

Installing it

The bridge ships inside the app — macOS and Linux, x86-64 and arm64 — so there is nothing to download and no runtime to install. Two cases: the agent running on this Mac, and an agent on a machine you connect to.

On the Mac running Onyx

One command

Point Claude Code at the bridge inside the app. It takes effect for every new session, in every directory:

$ claude mcp add --scope user onyx -- \
    /Applications/Onyx.app/Contents/Resources/mcp/OnyxMCP-macos-arm64

Then check it, with Onyx running:

$ /Applications/Onyx.app/Contents/Resources/mcp/OnyxMCP-macos-arm64 --probe

An agent on this Mac reaches Onyx over a Unix socket in your home directory — nothing listens on a network port for this. Or skip the terminal: the monitor's CONNECTIONS panel has a THIS MAC row with the same Install button every remote host gets.

On a machine you connect to

One click. The bridge installs over the connection you already have, registering itself with Claude Code on that host, and the monitor's CONNECTIONS panel shows a light per host: installed, current, or needs updating. A machine with several accounts gets a command you can hand to the others.

The install tells you if it can't reach Onyx afterwards, and names the symptom. Registered is not the same as reachable, and the alternative first symptom is an agent hanging for thirty seconds and reporting a timeout that explains nothing.

$ OnyxMCP --probe
no    ONYX_MCP_PORT=? — nothing listening
no    ~/.onyx/mcp.sock — nothing listening
YES   127.0.0.1:19432 (ssh -R) — Onyx answered
reachable

The tools

Ten of them, and an agent sees the same set whether it's running on your Mac or on a host three networks away.

Getting your attention

notify

Tell the user you need them. The alert attaches to the session it came from, so the indicator lights next to the work that's waiting — not in a general list. Urgent by default, because a quiet alert reaches nobody who isn't already looking.

Putting something on the screen

show_html

A real page in one of eight slots beside the terminal: a status summary, a table of results, a report whose every row links to the thing it describes. Links open in your browser. A complete document is shown as written; a fragment gets the app’s own dark styling.

show_diagram

Mermaid or PlantUML, rendered and zoomable. Explaining a refactor with the graph beats scrolling back through a description of it.

show_text

Text, code or markdown, syntax-highlighted, with wrapping chosen from the file type — off for code, on for prose.

show_model

A 3D model — OBJ, USDZ or STL — in a slot, for when the thing under discussion has a shape.

list_slots / clear_slot

What is on screen, and taking it down again. An agent that can see the slots can reuse one instead of stacking another panel on the pile.

Reading the codebase

analyze_deps

The dependency graph between the changed Java files in a repo, including the unchanged files that connect them, drawn as a diagram rather than listed as edges. Runs where the code is.

Knowing where it stands

onyx_status

Is Onyx reachable from this host, and if not, why and since when — answered from the host’s own records, without the desktop running. Which desktops have ever answered here, when each was last heard from, what the last attempt saw, and whether anything is queued.

onyx_guide

How to use Onyx, for agents. Tool descriptions answer "what does this one do"; this answers "what can I build with these together" — that publishing a page and alerting are two calls that pair, or that a remote agent cannot hand Onyx a file path.

Where an alert actually goes

The agent says one thing: whether this needs a person. Everything after that is your setting, per machine — an agent can't know which Mac you're sitting at, so it doesn't get to decide how far its message travels.

In the app

An indicator on the session it came from, the alert text in the menu bar, and a dock bounce that keeps going until you come back.

Notification Center

Every alert, urgent only, or never — your choice per Mac. A normal macOS notification, so it behaves like everything else on your screen.

Phone, and wrist

An Apple Watch mirrors a phone, never a Mac — so urgent alerts go out through ntfy, Pushover, a JSON webhook, or iMessage to yourself.

Slack and Discord webhooks work unmodified — the payload carries both of their field names. iMessage needs no signup at all, and being data rather than SMS it survives a carrier that filters gateway traffic. Settings has a Test button that reports the service's own answer rather than a green tick.

When Onyx isn't there

Your laptop sleeps. The network drops. The app is closed because it's Saturday. None of that should turn "the migration needs a decision" into nothing at all.

The alert is kept, not lost

An undelivered alert is queued on the host and retried when the agent's session starts, on the next successful call, and on a one-minute heartbeat. It carries the time it was sent, so a 2am alert doesn't claim to have happened when the network came back. It expires after 24 hours, because by then the moment has passed.

The bridge explains itself

Every failure says what this host has seen: whether Onyx has ever answered from here, which desktop, how long ago, over which route, and what the last attempt found. An agent that asks gets a real answer instead of concluding "it's broken" — and a desktop that answered a minute ago is reported as between contacts, not as gone.

A session that starts early isn't dead

An agent started while Onyx was closed used to spend its life with no Onyx tools. The bridge now answers the handshake itself and announces the tools when the app opens.

How it connects

Three routes, tried in order, and the first one that completes a handshake wins. A port that accepts a connection and then says nothing is not trusted — waiting one out costs exactly the thirty seconds an agent's startup has to spend.

ONYX_MCP_PORT
Inside a terminal Onyx opened, the app exports the port it's listening on. A local loopback connection, nothing else involved.
~/.onyx/mcp.sock
A Unix socket for agents running on the same Mac as Onyx, in a terminal Onyx didn't open.
Reverse-forwarded port
Every SSH connection Onyx makes carries a reverse forward, so an agent on a remote host reaches your Mac back down the connection you already opened. No inbound port, no listener facing the network, nothing to expose.

Alert text and pages travel over your own SSH connection to your own Mac. The exceptions are the ones you set up on purpose: a phone-forwarding service if you configure one, and PlantUML diagrams, whose source is encoded into an image URL — Mermaid renders locally. The privacy page says exactly where and when.

It's in 0.19

Install Onyx, connect a host, and click install in the CONNECTIONS panel. The agent on that machine has the tools the next time it starts.