RheoclesREE-oh-kleez

The menu bar app

A popover over whatever you are doing. Every stream with an arm toggle, one Record button, and a mark in the menu bar that tells the truth about the take.

Rheocles.app has no window and no Dock icon. It lives in the menu bar, opens as a popover, and is a thin client of rheocles-core over the same API you get. Nothing in it is a feature the API lacks; nothing in the API is a feature it lacks.

The mark

The mark is the state. It is a template image, so it takes the menu bar’s colour, and it is drawn from shapes rather than a SwiftUI view — a bare view as a MenuBarExtra label renders with no colour at all, which Sonocles paid to learn.

state the mark
idle, nothing armed the whole mark at 40 %
something armed the strokes in outline
recording the strokes filled
a stream joined late a shorter stroke that starts to the right of the bar

You can read the take from across the room without opening anything, and — the case the ochre exists for — you can see from across the room that six cameras are still armed.

The popover

Streams. Every camera, microphone, display and system audio, each with an arm toggle. Armed rows are ochre. Audio streams show a level meter while armed. Windows are listed only when Show windows is on in settings.

Preview, on demand. One stream at a time, behind a button — not a wall of thumbnails. Each look is one GET /preview/{stream}: a single JPEG grabbed by a polite second opener that never disturbs an armed or recording take, or, for an audio stream, the peak level that drives the meter. Nothing is captured when nobody is looking, and one preview runs at a time.

Record / Stop. One button. Record is POST /record: create and start together. The current take’s name and elapsed time sit beside it, and under it, when the armed set allows one, the Also save a single file checkbox.

After stop. The outcome line — complete or incomplete with its reason — with an Open in Finder button for that take’s folder; a Single file · combined.mov line when the take asked for one; and the recent takes, folded, each with its own Open in Finder.

Settings. Output root and codec (HEVC or ProRes 422, one global setting) — PATCH /settings, and the root will not move while a take is active; Show windows; and the bearer token, shown as a pairing code with a rotate button that is POST /token/rotate. The output root has an Open in Finder button too.

Open in Finder

A folder glyph, in Aegean, wherever a destination is shown:

beside reveals the call
the outcome line after complete or incomplete that take’s folder POST /takes/{id}/reveal {}
each recent take that take’s folder POST /takes/{id}/reveal {}
the Single file · combined.mov line, once complete the file, selected in its folder POST /takes/{id}/reveal { "path": "combined.mov" }
the output root, in settings the root POST /reveal {}

The app never opens the Finder itself. Every button is a call to the daemon, which does the revealing on its own Mac — the same call Pteroprompter makes from a browser page, which cannot open the Finder at all, and the same one the NativePHP app makes. One implementation, on the one process that has the files. The button does nothing visible when the take folder is gone, because the daemon answers 404 and there is nothing to show; and it does nothing at all against a daemon older than this feature, which answers 404 not_found for the route — see Troubleshooting.

Also save a single file

A checkbox in the take bar, beside Record, labelled Also save a single file with combined.mov · no re-encode after it. It is the daemon’s settings.combine: ticking it is PATCH /settings { "combine": true }, so it is remembered across launches and shared with every other front end on the same daemon, and every take from then on is created with the daemon’s default until you untick it.

It is shown only while at most one video stream is armed. Arm a second display or camera and the checkbox goes — hidden, not greyed — because a passthrough mux has no single file to make from two pictures. Disarm one and it comes back, still ticked if it was. The setting is not changed by hiding it; a take recorded while it is hidden is created without a combined file and the daemon says so in warnings.

After stop, the take bar shows Single file · combined.mov with a pulse while the daemon is writing it (combined.state is pending), a green dot and an Open in Finder button when it is complete, or the reason in oxide when it failed. A finished take that has no combined file and at most one video stream — one recorded with the box unticked, or one whose combine failed — shows a Combine now button instead, which is POST /takes/{id}/combine. The take’s own outcome line does not change on a failed combine; the per-stream files are the take. What the file is and is not — one video track, every audio stream as its own track, no re-encode, no mixdown — is on Recording a take.

The daemon

The app bundles rheocles-core and launches it if nothing answers on 7447; if something does, it uses what is running. Two front ends on one machine — the menu bar app and the NativePHP app, or a future Pteroprompter — share one daemon. There is no LaunchAgent in the MVP: the daemon lives as long as something is talking to it.

The daemon’s output root, codec and combine default live in settings.json beside the token. Launching rheocles-core --output-root <path> overrides the persisted root for that run, and --settings-file <path> points it at a different settings file altogether — the way to point a test at a scratch volume without touching your settings.

Reviewing the UI without a screen

Terminal window
Rheocles.app/Contents/MacOS/Rheocles --render-preview ./previews

renders every popover state to PNG offscreen, as Sonocles does, so a change can be reviewed from a build log. AppKit-backed controls do not rasterise this way; anything in the popover that needs to appear in a preview is drawn from shapes.

Style

The app follows docs/BRAND.md and this site, not Pteroprompter, and it is not a dark theme: the same limestone ground and ink text as this page, aegean for the signature, ochre armed, oxide recording, olive complete, script for a value it does not have. The only dark surface is a code or data block, as here.