A workspace for getting things done
Everything you're waiting on,
one keystroke away.
More of the work is being done by something that isn't you — an agent, a pipeline, a training run, a reviewer. Onyx is a jet-black overlay that drops over whatever you're doing and shows the state of all of it at once: what's due today, which sessions are still producing output, which pull requests are blocked, which builds are red, and how the machines are holding up.
Underneath it, terminals that are already connected. Close the lid, change networks, walk away for a day — come back and start typing.
v0.15 · macOS 14 or later · Apple Silicon · free and open source
you@workstation ~/src/api main
$ swift test
Executed 854 tests, with 0 failures
$
One key, and there it all is
The overlay drops over the terminal — over anything — and answers the question you actually have at 9am, or after lunch, or when a build finally finishes: what is going on, and what needs me?
Today
4 today · 7 by tmrw
- Send the revised contract 10:00
- Review Q3 forecast 13:30
- Book conference travel
- Renew the wildcard cert 17:00
Straight from Apple Reminders. Nothing is copied anywhere.
Session notes
- ⌘1 api rebasing onto main
- ⌘2 trainer epoch 14/40 — ETA 2h
- ⌘3 migrate waiting on my review
- ⌘4 logs tailing prod
The dot is real output, not a heartbeat. Click one to land in it.
Pipelines
- ● acme/api main 4m 12s
- ◐ acme/console feat/billing 2 of 6
- ✕ acme/infra main deploy
Open pull requests
-
acme/api#412 3 unresolved
Retry policy for the ingest queue
-
acme/console#98 ready to merge
Billing settings page
Illustration · sample data
A terminal knows what it ran. It doesn't know what you owe anyone.
So the overlay tracks the three things that actually decide what you do next.
Apple Reminders
Today, without opening a second app
Onyx reads Reminders directly through EventKit — your lists, on your Mac. Nothing is copied into Onyx, nothing syncs anywhere, and anything you tick off in Reminders on your phone is gone from the overlay by the next refresh.
Two counts sit in the corner permanently: how much is due today, and how much will be due by the end of tomorrow — so you can see the load coming, not just the load now. Press R and the list collapses to just those, still grouped by list, with anything not due today dimmed. Press S for the across-the-room view and today's list runs down the left beside the charts.
And when a reminder is really a job for something else, you can hand it off: with a flowtree controller configured, a reminder can be submitted straight to an agent workstream from the overlay.
- Send the revised contract overdue
- Review Q3 forecast 13:30
- Draft the board update tomorrow
not due today → dimmed, not hidden
Session notes
Sessions that remember what they were for
Long-running work is the norm now — a fine-tune, a migration, an agent halfway through a refactor. Come back after lunch and the hard part isn't reconnecting, it's remembering which of nine terminals was which.
So every session takes a note — ⌘; and type what it's for. The overlay lists them in the same order as your ⌘1–9 favorites, with the shortcut shown next to each, and clicking one drops you into that session and closes the overlay.
Next to each note is an activity dot, and it's an honest one. It comes from hashing the visible pane with tmux's status bar excluded — so a ticking clock, a redraw, or a reconnect repainting the screen doesn't register as work. Green means that session genuinely produced output; grey means it has been quiet for a while, whatever it claims.
- ⌘2 trainer epoch 14/40 — ETA 2h 4s ago
- ⌘3 migrate waiting on my review 6m
- ⌘4 logs tailing prod 2h
GitHub & GitLab
The queue in front of a merge
Open pull requests and merge requests arrive in one merged list — GitHub via its GraphQL API, GitLab via v4 — so a codebase split across two forges reads as one pile of work. Each row carries the two things that decide whether you can stop thinking about it: how many review threads are still unresolved, and whether it would actually merge right now under the repo's own branch protections.
Pipelines sit above them — Actions runs and GitLab pipelines side by side, rolled up from their individual jobs, so a partial failure shows as a partial failure. You can add one straight from an open PR: Onyx knows the head branch and offers the pipeline running on it.
Both are polled with a token you supply, one cycle at a time, and both stop the moment you clear the token.
- ●acme/api main 4m 12s
- ◐acme/console feat/billing 2 of 6
- ✕acme/infra main deploy
GitHub acme/api#412 3 unresolved
Retry policy for the ingest queue
GitLab platform/deploy!87 ready to merge
Pin the runner image
Working with agents
Built for the part where you're not the one typing
An agent working in a terminal has two failure modes that cost you real time: it finishes and you don't notice, or it stops to ask permission and you don't notice. Both are visibility problems, and the overlay is where they get solved.
Permission requests come to you
Claude Code hooks report into Onyx, so its sessions show up as sessions: which are running, what tools they've been reaching for, and how long since each one did anything. A blocked agent stops being a tab you forgot about.
Turn on permission gating and it goes further — a PreToolUse hook holds the agent while the request is shown in Onyx, and your approve or deny is routed back to the waiting hook. It's off by default; leave it off and Claude prompts in the terminal exactly as it always has.
Permission requested · api
Bash — terraform apply -auto-approve
Agents can put things on your screen
Onyx runs an MCP server, so an agent working in any repo — on your Mac or on a machine you're connected to — can push a diagram, a data model, or a block of text into one of eight numbered slots and have it appear next to the terminal. Explaining a refactor with a rendered graph beats scrolling back through the description of one.
There's a dependency analyzer in there too: point it at a Java tree and it draws the graph rather than listing the edges.
Artifact slots
show_diagram · show_model · show_text · analyze_deps
Connections that stay connected
Most of the work in Onyx went here. Not into features — into the unglamorous business of a session still being there when you get back to your desk.
2
connections per host
One active, one warm standby. Every terminal, every poll, every file listing rides those two as multiplexed channels. Nothing else opens a connection — so a flaky network can never turn into a connection storm against your server.
~100ms
failover
When the active connection dies, the standby is already authenticated and waiting. Your session reattaches through tmux with your scrollback intact. No probing, no backoff ladder, no ten-second wait.
0
prompts to reconnect
Sleep, wake, change networks, lose Wi-Fi for six hours. Nothing parks waiting for you to press a key: the moment a host is reachable again, the terminal is live. If a host is genuinely gone, it says so — in the host's own words.
Everything else it does
Every machine you own, at a glance
CPU, memory and GPU as live charts — including AMD cards through amdgpu's own counters and Ryzen AI NPU residency, not just Apple Silicon. Docker containers ranked by what's actually burning CPU. Hosts you aren't looking at keep being sampled, so the picture is current when you switch to one.
A remote file browser that knows git
Branch, staged files and working changes sit above the listing. Search by name or file type across a deep tree. Favourite folders are drawn as a treemap, so a folder inside a folder looks like one — and two folders with the same name are told apart by what contains them.
Code navigation on the remote machine
A language server runs where the code lives, not on your laptop. Jump to a definition, find references, list the implementors of an interface or the subtypes of a class — over SSH, without checking anything out locally.
Hours, tracked without asking
If you use Timing, the week reads back as hours per day and per project, with a ratio bar for how the week actually split. It answers "where did this week go" without opening anything.
Notes, palette, browser tabs
A notes panel that stays out of the way, ⌘K for everything else, and real browser tabs when the documentation belongs beside the terminal instead of in another app. There's a live dashboard you can open as a browser new-tab page, and a screensaver that draws your fleet's CPU.
Quiet by construction
Pause a host and Onyx stops reaching for it entirely — favourites, notes and sessions all kept, zero connection attempts, terminals say why. It matters when one machine on a bad link is degrading the network for everything else. Nothing un-pauses itself.
None of this phones home. There are no analytics and no account to make. Reminders are read on your Mac through EventKit; GitHub and GitLab are polled directly with tokens you supply, and stop the moment you remove them; your notes, session notes and settings are files in your home directory. The one place content leaves your machine without you aiming it somewhere is diagram rendering, and the privacy page says exactly where and when.
Get Onyx
Download the app
Signed and notarized. Drag it to Applications and open it.
Onyx 0.15 for MacmacOS 14 or later · Apple Silicon
Or build it yourself
It's a Swift package. The install script builds it and puts the app in Applications.
git clone https://github.com/almostrealism/onyx
cd onyx
./install.sh
All releases →
Onyx uses tmux for session persistence — it needs to be installed on tmux on the machines you connect to, not necessarily on your Mac. Read the source .