Releases: myWsq/coflux
Release list
Coflux v2.4.0
Coflux 2.4.0
The executor actually runs, and Command-P jumps anywhere in the workbench.
The desktop app, the runtime and the center all change. An in-app desktop update is enough for the two things a Mac sees; the sharper device-id error appears only after the center running this release is deployed.
Highlights
-
coflux executor runworks. Since 1.2.0 the desktop app has registered its executor host under a capability name the daemon does not accept, so every registration was refused. The only symptom was a report that Coflux.app was not running, while the app was open and the settings page still showed the model as ready. The host now declares the name the daemon already gates on. -
One executor, hosted by whichever macOS process has a runtime. The implementation lives in one package. Coflux.app hosts it in its main process, and a daemon installed from npm on macOS hosts the same package. When both could host, the daemon takes it; the two never race, and a worker upgrade no longer kills a task that has already started. Linux still has no executor: the kernel sandbox that bounds a run has no equivalent there, so a host is not registered.
-
Command-P opens a navigation palette. One query reaches a workspace, a project, a running terminal or a device. Exited terminals do not appear. With an empty query the place you were in before this one is first and already highlighted, so Command-P then Return bounces between two places. Command-[ and Command-] filter by kind while the palette is open.
-
A device id that names nothing says so. The first eight characters of a device id, typed without the
coflux:device:prefix, used to be reported as the device being offline. The account API now says that no device of this account has that id, on bothcoflux device execandcoflux project import. A device that exists and is disconnected still reports the outage.
Install or update
Mac: install coflux-2.4.0-arm64.dmg, or use the desktop app's update action. The desktop app requires macOS 26+ and Apple Silicon. The in-app update keeps the live runtime, so local terminals stay up; the executor fix and the palette are in the app and do not need a runtime restart.
Headless macOS, where the daemon itself hosts the executor:
npm install -g cofluxd@2.4.0
cofluxd update
cofluxd restartcofluxd restart ends local terminals. It is required on this path: the service unit has to be rewritten with the node runtime the host runs under, and a worker-only hot upgrade does not do that.
Linux: this release does not enable the executor there. The packages are published at the same version; updating is optional and changes nothing you can see.
Upgrade impact
No protocol change and no schema migration. A desktop or daemon from 2.3.x keeps working against a center that has or has not yet taken this release.
The device-id sentence is served by the center. Until the center is deployed, a mistyped id still reports an outage.
A Mac running Coflux.app is covered by installing the app. Every other macOS machine that should host the executor needs cofluxd update && cofluxd restart.
Known gap
Linux has no executor until a kernel sandbox exists. The command says so, rather than running unbounded.
Full changelog: v2.3.0...v2.4.0
Coflux v2.3.0
Coflux 2.3.0
A desktop-only release: a custom executor endpoint finally survives being added, and the conversation paper reads at Cursor's measure.
Nothing in the center or the runtime changes. Install the desktop app; daemons on other machines need no action.
Highlights
-
A custom endpoint you add is actually saved. Adding a relay or an Ollama endpoint looked like it worked — the row appeared in the list — but nothing ever reached the center, and reopening the settings page lost it. An endpoint save submits the whole executor configuration, and the main process refused the entire save at its first selection check: on an account that had not picked a model yet, the empty provider and model in the form failed validation and took the endpoint down with them. An unset selection is now a valid stored state, which is what "endpoints configured, model not chosen yet" has always meant. Half a selection is still refused.
-
The endpoint area reports its own outcome. A failed save used to render its error half a screen away at the bottom of the model card, while the list kept showing the endpoint that had not been stored. The list now rolls back when a save is refused, and the message appears where the action was.
-
A saved endpoint reaches the Provider dropdown without closing the page. The catalogue re-fetches on every settings snapshot, so an endpoint added here — or on another device — shows up in the dropdown right away.
-
Deleting the endpoint you are currently using works. It used to be refused forever: the runtime unregisters the endpoint before validation runs, so the saved selection pointed at a provider that no longer existed. An endpoint change now projects the saved selection onto what still resolves afterwards, clearing it when it does not, which leaves the account in the "not configured yet" state instead of a dead end.
-
The conversation paper is set at Cursor's typography. The overlay capped its measure at 68 characters, which on this app's 13px type scale is a 490px ribbon down the middle of a wide terminal pane. The column is now a fixed 840px, centered, with body text at 15px on a 24px rhythm, block spacing and list indents on the same em-based rhythm, and a person's own turns drawn as outlined cards rather than solid blocks. Every number comes from Cursor 3.20.17's shipped stylesheets. In a pane narrower than the measure nothing overflows: the column simply fills the pane, as before.
Install or update
Mac: install coflux-2.3.0-arm64.dmg, or use the desktop app's update action. The desktop app requires macOS 26+ and Apple Silicon.
Linux or headless hosts: this release contains no runtime changes, so there is nothing to update. The packages are published at the same version for consistency:
npm install -g cofluxd@2.3.0
cofluxd update
cofluxd restartUpgrade impact
None. No schema migration, no server configuration, and no daemon capability is involved. A machine running 2.2.x daemons works unchanged with the 2.3.0 desktop app.
Known gap
While the executor catalogue is still loading — the first few hundred milliseconds after the settings page opens — the selection projection cannot tell a built-in provider from a custom endpoint a save is deleting, so it keeps the selection and deleting the endpoint in use is refused once. Reopening the page or retrying after it has loaded works.
Full changelog: v2.2.1...v2.3.0
Coflux v2.2.1
Coflux 2.2.1
A desktop-only fix: the custom endpoint dialog is readable again, and settings rows have room to breathe.
Nothing in the center or the runtime changes. Install the desktop app; daemons on other machines need no action.
Highlights
-
The custom endpoint dialog no longer clips its own title. Adding a relay or an Ollama endpoint opened a dialog whose heading was cut off by the top edge, with the body inset and the header not — the dialog had opted out of the shared frame and laid out its own content, which stripped the padding from the header along with it. It now uses the same frame as every other dialog in the app, so the title sits where titles sit and the body scrolls under a fixed header when the fields run long.
-
Its footer matches the rest of the app. A divider, right-aligned actions, and the Esc and Enter hints the other dialogs already carry. Delete moves to the left, away from the button you press to confirm. Enter in a single-line field saves; Enter in the model id box still adds a line.
-
An empty form no longer opens with a warning on it. The dialog used to greet a new endpoint by pointing out that it had no id yet. The missing-field hint now waits until you have typed something.
-
Settings rows have vertical padding. Rows carried 4px of it against 16px on the sides, which pressed each row's description against the next row's name. They now carry 10px, one step below the horizontal value so a row still reads as a row rather than as a small card of its own.
Install or update
Mac: install coflux-2.2.1-arm64.dmg, or use the desktop app's update action. The desktop app requires macOS 26+ and Apple Silicon.
Linux or headless hosts: this release contains no runtime changes, so there is nothing to update. The packages are published at the same version for consistency:
npm install -g cofluxd@2.2.1
cofluxd update
cofluxd restartUpgrade impact
None. No schema migration, no server configuration, and no daemon capability is involved. A machine running 2.2.0 daemons works unchanged with the 2.2.1 desktop app.
Full changelog: v2.2.0...v2.2.1
Coflux v2.2.0
Coflux 2.2.0
Executor model settings belong to your account, and an agent's conversation is a page you can copy from.
This release changes the center, the runtime and the desktop app together. Deploy the center first, then update daemons, then install the desktop app.
Highlights
-
Executor model settings are account-wide and validated at save time. Choosing which model runs your tasks used to mean typing three free-text strings — provider, model id, API key — into one machine, with no list to choose from, no way to reach a custom endpoint, and no feedback until an agent dispatched a task and failed. Settings now live in the center: pick a provider and a model from a list, add a custom OpenAI-compatible endpoint, test the connection before saving, and have every desktop on the account see the same configuration.
-
The API key is stored encrypted and never travels further than it has to. Credentials are encrypted at rest in the center with a key held only in the server's environment, and the renderer never sees them — the settings it can read carry
hasApiKey: booleanand nothing else. Nor do credentials reach the model runtime through the provider registration path, where a value beginning with!or$would be resolved as a shell command or an environment variable. -
Dispatching a task still works with the center unreachable. The read path is local: the daemon writes the settings it receives to
$COFLUX_HOME/executor-settings.json(0600) and the desktop app reads that file directly. Only changing the configuration needs the center, and the settings controls say so when the machine is offline. -
A reconnect no longer leaves the executor host unregistered. When a device channel dropped and came back, the desktop stopped announcing itself, so agents were told "Coflux.app is not running" while it plainly was. Announcements now follow the transport's connection generation rather than the daemon id, which a reconnect leaves untouched.
-
Read an agent's conversation as text, not as wrapped terminal output. Copying prose out of a terminal gives you text broken by hard newlines: Claude Code and Codex render through Ink, which wraps to the terminal width itself, so every newline is one the agent really emitted. A button in the terminal's top-right corner now expands an overlay showing that terminal's conversation — your prompts and the agent's prose — as a rendered page you can select and copy from. Esc or a second click collapses it, and the terminal keeps running underneath.
-
The overlay works for remote terminals too. The transcript travels over the existing workspace-exec channel, which already routes to whichever device owns the workspace, so a terminal on another machine takes the same path. Only a bounded tail is read, and the page states when the head was truncated. Remote devices need the runtime from this release.
Install or update
Mac: install coflux-2.2.0-arm64.dmg, or use the desktop app's update action. The desktop app requires macOS 26+ and Apple Silicon.
Linux or headless hosts:
npm install -g cofluxd@2.2.0
cofluxd update
cofluxd restartUpgrade impact
Daemons must be updated for both features. The center checks a capability name before it delivers executor settings and stays silent when it is absent, so an older daemon never receives the configuration and the desktop app reports that the local daemon is too old. The conversation overlay likewise needs the worker from this release to learn an agent's session id. A desktop release bundles its own daemon, so a Mac running the desktop app is covered by installing it; every other machine needs cofluxd update && cofluxd restart.
Self-hosted centers need one new environment variable. COFLUX_EXECUTOR_KEYS holds <keyId>:<base64 of 32 random bytes>, comma-separated, with the current key first; generate one with openssl rand -base64 32. The server still starts without it and refuses credential writes with a readable error rather than storing anything in plaintext, but a malformed value fails startup deliberately. Back this key up: without it, stored credentials cannot be decrypted, and the affected users are asked to enter their API key again. Ciphertext carries a key-id prefix, so rotation needs no downtime and no re-encryption of the table.
The schema migration in this release is a one-way door. It creates one new table and touches nothing existing, but once applied, an older server build refuses to start against that database. It requires PostgreSQL 15 or newer.
Full changelog: v2.1.2...v2.2.0
Coflux v2.1.2
Coflux 2.1.2
Command keys reach the menu again inside an agent TUI, and the terminal is a clean sheet of paper.
This is a patch release on top of 2.1.1. Everything in it lives in the desktop terminal. The runtime, the CLI and the center are unchanged, so no device needs a runtime restart and no fleet-wide coordination is required.
Highlights
-
⌘C and ⌘V work inside Claude Code and other full-screen agent CLIs again. Since 2.1.0 both keys were dead in an agent TUI, and ⌘V additionally typed a literal
vinto it. In a plain shell in the same window they still worked, and that difference was the whole explanation: 2.1.0 enabled the kitty keyboard protocol, which the program holding the PTY negotiates at runtime. An agent TUI negotiates it; a plain shell does not. Once active, the terminal encoded every keystroke — ⌘ included — as an escape sequence and consumed the event, so the native Edit menu's copy and paste accelerators were never reached. The menu was never broken; it was starved. The ⌘ class is now handed back to the app before that encoder runs, and the protocol stays on, so Shift+Enter and the other keys it enables are unaffected. -
The same fix returns ⌘X, ⌘Z and ⌘R. The damage was wider than the two keys that were reported: cut, undo and window reload were dead inside a negotiating TUI for exactly the same reason. ⌘A is the one key with its own rule — it selects the terminal buffer first and then yields, which is the behaviour it had in 2.0.2. Ctrl and ⌥ are deliberately left to the terminal: Ctrl+C still interrupts, Ctrl+D still sends EOF, and ⌥ remains the Meta prefix.
-
The vertical bar down the left edge is gone. It was the shell-integration marker that flags where each command began, asking for a height of
100%— which resolved against the whole terminal screen rather than a single line, so consecutive commands stacked into one continuous strip that read as a stray scrollbar. The marker is one line tall again, which is what it was meant to be all along. -
No black band below the last row. xterm's own stylesheet paints the scrollable viewport pure black, and the theme colour applied at runtime reached the layers underneath it but not the viewport itself. Any moment the rendered rows fell short of the container — while a terminal was attaching, inside a resize, or simply because rows do not divide the window height evenly — that black showed through. The paper colour is now written onto that element directly, so the gap is the same colour as the terminal.
-
The last row is whole. The terminal's inner padding sat on the surrounding container, where the fit calculation could not account for it, so the grid was sized for one row more than the panel could show and the bottom row was sliced by its edge. The padding now sits on the terminal itself: the sizing is correct and the paper colour extends into the padding.
Install or update
Mac: install coflux-2.1.2-arm64.dmg, or use the desktop app's update action. The desktop app requires macOS 26+ and Apple Silicon.
Linux or headless hosts:
npm install -g cofluxd@2.1.2
cofluxd update
cofluxd restartNothing in this release changes the runtime or the CLI; cofluxd@2.1.2 publishes alongside the desktop app to keep one product version across every component. A device already on 2.1.1 gains nothing from updating it.
Upgrade impact
Desktop only. Install the update and the fixes are live in every terminal the app opens. A supervisor holding live terminals does not need to restart for this release.
Keyboard behaviour changes only for ⌘. If you relied on a ⌘ chord being delivered into a program inside the terminal, it now goes to the app's menu instead. No ⌘ chord is bound to anything terminal-side in this app, so this should be invisible in practice.
Full changelog: v2.1.1...v2.1.2
Coflux v2.1.1
Coflux 2.1.1
Chinese text sits on the terminal grid, and the lines have room to breathe again.
This is a patch release on top of 2.1.0. The control protocol is unchanged, the center is untouched, and nothing here requires a coordinated fleet-wide upgrade.
Highlights
-
The terminal ships its own font, so CJK lands on the grid. A terminal is a fixed grid, and xterm gives one CJK codepoint exactly two cells. The font stack this app asked for —
"SFMono-Regular", Consolas, "Liberation Mono", Menlo— has nothing installed on macOS except the last one, so latin fell to Menlo at 0.602em while Chinese fell through to PingFang SC at 1.0em. Chinese characters then sat in cells wider than the glyphs, and anything drawn in columns drifted apart: table borders, tree guides, aligned output from an agent. Maple Mono CN is now bundled with the app, with a latin advance of 0.600em against a CJK advance of 1.200em — an exact 2:1 that fills those two cells precisely. It is embedded rather than fetched, so there is no first-paint flash and no network dependency; the app waits for the font once during boot, because xterm caches its character measurements synchronously and permanently. -
Terminal line height returns to 1.25. 2.1.0 followed a comparable editor's defaults down to a line height of 1.0, which cut the leading by a fifth and made long output feel packed. The terminal now renders at 12px with line height 1.25 — the spacing it had through 2.0.2.
Install or update
Mac: install coflux-2.1.1-arm64.dmg or use the desktop app's update action. The desktop app requires macOS 26+ and Apple Silicon.
Linux or headless hosts:
npm install -g cofluxd@2.1.1
cofluxd update
cofluxd restartUpgrade impact
The download is larger. Four woff2 faces add roughly 23MB to the desktop bundle. That is the cost of a terminal that renders Chinese correctly without depending on what a machine happens to have installed, and it is paid once per update.
Nothing outside the desktop app changes. The runtime, CLI and center are identical to 2.1.0; a device already on 2.1.0 needs no runtime restart for this release. If you have not yet picked up the 2.1.0 supervisor changes — session locale, SSH_TTY, deeper scrollback — those still need cofluxd update and cofluxd restart on each device.
Full changelog: v2.1.0...v2.1.1
Coflux v2.1.0
Coflux 2.1.0
The terminal is the release. Emoji and CJK text stop corrupting the line, copying works inside fullscreen agent TUIs, an agent's own copy command reaches the machine you are watching from, and the shell finally starts with a usable locale. Alongside it: entities you can paste into an agent, a project import that no longer requires the desktop, and failures that name what actually went wrong.
Highlights
-
The desktop terminal feels like a terminal. The renderer moves to the xterm 6.1 cohort with Unicode 11 width tables and the kitty keyboard protocol, so emoji-heavy TUIs — Claude Code above all — render at the right cell widths without cursor drift or trailing garbage, and modifier combinations such as Shift+Enter reach the application. Visual defaults now match what a comparable editor ships: a non-blinking block cursor, line height 1, and a 4.5 contrast floor that makes the theme's dim colours readable instead of leaving them at their authored contrast. ⌘F searches the scrollback with match highlighting and a count, right-click opens a menu with copy and paste (macOS previously offered nothing at all),
file:linereferences in output become links that open in the workbench, and command boundaries the shell integration already emitted become navigable — jump to the previous or next command, or copy the last command's output. Resizing the window no longer storms the PTY with one resize per observer callback, and high-throughput output is coalesced before it reaches the wire, so a large build log is far less likely to overflow into a gap-and-repaint. -
Session shells start with a locale. A PTY session inherited whatever the supervisor was launched with, which under launchd is nothing:
LC_CTYPE="C", noCOLORTERM, and every wide-character width judgement wrong at the source. When all three locale variables are empty the supervisor now injects a UTF-8 default, declares truecolor, and identifies the host terminal as coflux. A deliberately non-UTF-8 locale you set yourself is passed through untouched — the bug was an empty locale, not a wrong one. Gap recovery also keeps 5000 lines of scrollback instead of truncating a client's history to 2000. -
Copying out of a terminal works, including from an agent. Inside a fullscreen TUI holding mouse tracking, dragging selected nothing, so there was nothing for ⌘C to take; ⌥+drag now forces a local selection the way every other macOS terminal does, and ⌥+click no longer injects a burst of arrow keys into the application. Separately, a program that writes OSC 52 to put text in your clipboard now reaches it: the desktop parses the sequence itself, gates it behind the visible, owned panel so a background tab cannot overwrite what you are using, and answers a clipboard query with zero bytes. And agent CLIs now emit OSC 52 at all — a coflux terminal declares itself remote through
SSH_TTY, sogrok doctorreportsnative: remote (pbcopy)instead of writing to the clipboard of whatever machine the PTY happens to run on. Watching a terminal from a second computer and copying from the agent running in it now puts the text where you are sitting. -
Entities you can paste. Every device, project, workspace and terminal has a handle —
coflux:workspace:3f2a1b7c— accepted anywhere its UUID is accepted and returned alongside every entity the account API hands back. A bare UUID says nothing about what it names; a handle is visibly coflux's and visibly typed, which is what an agent needs when you paste one at it. The desktop's sidebar and terminal tab menus copy them, iOS copies them on long-press, and the<coflux-session>block an agent receives now carries the handles of its own coordinates. -
coflux project import <path>turns a folder into a project from the CLI. The capability existed end to end but only the desktop wizard could start it, so an agent that wanted a new repository as a project had to stop and ask you to click Import. The path is resolved on the target device,--deviceselects the machine, and an already-imported repository reports itself instead of creating a duplicate. -
Failures say what failed. Local enrollment problems no longer interrupt with a modal alert; they land in the machine status line and the enrollment step that owns the retry, and the message names the stage that actually stalled instead of claiming a cleanup timeout for every phase — including its claim that a retry record had been kept, for a stall with nothing pending. A refused login likewise stops insisting that the username or password was wrong: an expired session, a rate-limited address, and an obsolete client each now read as themselves. And
taskRemoveanswers every request — removing a terminal that is already gone is an idempotent success rather than a request that can only time out. -
⌘R reloads the window, rebuilding the renderer without leaving main-process state behind.
Install or update
Mac: install coflux-2.1.0-arm64.dmg or use the desktop app's update action. The desktop app requires macOS 26+ and Apple Silicon.
Linux or headless hosts:
npm install -g cofluxd@2.1.0
cofluxd update
cofluxd restartUpgrade impact
The control protocol is unchanged. A 2.0.x center serves 2.1.0 devices and desktops, and a 2.1.0 center serves 2.0.x ones; no coordinated fleet-wide upgrade is required.
The terminal environment and scrollback changes live in the supervisor, which cannot hot-upgrade, because it owns the PTYs. A worker upgrade does not carry them. On macOS the app updates itself, notices that its bundled supervisor outranks the running one, and asks for a runtime restart when your terminals can end. On Linux and other headless hosts, run cofluxd update and then cofluxd restart once tasks finish. Until a device restarts its runtime, shells there keep starting with an empty locale and agent CLIs keep writing to the PTY host's clipboard. coflux device list shows which devices still run an older supervisorVersion.
The account API additions — entity handles and project.import — need the center deployed, since both are server-side. Desktop copy affordances work without it, because a handle is composed locally.
Operators of a self-hosted DERP relay: admission now has a published, authenticated route. Set COFLUX_DERP_ADMISSION_TOKEN on the center, expose /derp-verify through the proxy that already terminates TLS for it, and point the relay's -verify-client-url at https://derp:<token>@<center>/derp-verify. This replaces reaching the loopback listener through an SSH tunnel, whose target address had to be edited on the relay host every time the center moved — and was not, the one time it mattered. See the transport document.
Full changelog: v2.0.2...v2.1.0
Coflux v2.0.2
Coflux 2.0.2
Closing a terminal no longer raises an error, and the iOS app can reach the sessions that live on a device itself.
This is a patch release on top of 2.0.1. The control protocol is unchanged, the center is untouched, and nothing here requires a coordinated fleet-wide upgrade.
Highlights
- Closing a terminal stops reporting its own teardown as an error. Every close had a good chance of raising a red toast — a PTY input write failure reported as
Input/output error (os error 5), with the session marked terminated — that had to be dismissed by hand. The error was describing the close itself:EIOon a PTY master write has exactly one meaning, that the slave side has no open descriptor left, which is precisely what closing a terminal does. The bytes still in flight are not keystrokes either; they are the terminal's own automatic replies to capability queries issued by TUI agents, plus a focus-out sequence. Three neighbouring paths produced the identical toast and are now log-only: a benign zero-byteEIOwrite, an input enqueued after the writer thread stopped, and an input for a session the reader already dropped. A partial write and any non-EIOfailure stay fatal, so the replay-prefix guarantee is untouched, andsession_not_foundstays loud on attach, stop, snapshot and resize, where clients depend on it. - iOS reaches device-level sessions. Terminals that run in a device's own directory workspace — the ones the desktop sidebar puts one click below each device — were unreachable from the phone: the workspace list renders only workspaces that belong to a project, and the device panel was a deliberately read-only health view. A device row is now a way in. It carries that device's running-session count and opens the existing task deck for those sessions, with the title resolving to the device name. On a device that has never opened a terminal, the empty state creates the first one — resolving
~to an absolute home path through the device browse channel first, and starting the task it creates, so the terminal lands running rather than behind a "not started yet" banner. An offline device can still be opened to read history, with creation disabled and the reason shown. The iOS app is delivered through TestFlight and is not an artifact of this Release.
Install or update
Mac: install coflux-2.0.2-arm64.dmg or use the desktop app's update action. The desktop app requires macOS 26+ and Apple Silicon.
Linux or headless hosts:
npm install -g cofluxd@2.0.2
cofluxd update
cofluxd restartUpgrade impact
Upgrade the devices, not the center. No server or protocol change ships in this release; a 2.0.0 or 2.0.1 center serves 2.0.2 devices and desktops unchanged.
The terminal-teardown fix lives in the supervisor, which cannot hot-upgrade, because it owns the PTYs. A worker upgrade does not carry it. On macOS the app updates itself, notices that its bundled supervisor outranks the running one, and asks for a runtime restart when your terminals can end. On Linux and other headless hosts, run cofluxd update and then cofluxd restart once tasks finish. Until a device restarts its runtime, closing a terminal there keeps raising the toast — the symptom this release exists to remove. coflux device list shows which devices still run an older supervisorVersion.
The iOS change arrives through TestFlight, independently of this Release.
Unchanged from 2.0.1: real internet and NAT acceptance across a reproducible network matrix, resource measurements at 0/1/10 demanded devices, and packaged GUI/keychain lifecycle acceptance remain unverified, and the loopback latency regression recorded in the 2.0.0 notes stands. Real-machine acceptance of both changes in this release — a daemon restart followed by closing terminals, and the iOS device walkthrough — is pending.
Full changelog: v2.0.1...v2.0.2
Coflux v2.0.1
Coflux 2.0.1
Remote connections stop failing on devices whose clock trails the center, and the iOS app can reach devices again.
This is a patch release on top of 2.0.0. The control protocol is unchanged, the center is untouched, and nothing here requires a coordinated fleet-wide upgrade.
Highlights
- A device a few milliseconds behind the center no longer refuses every remote connection. The center stamps a channel grant's expiry at exactly the maximum TTL, and the worker rejected any grant whose remaining validity exceeded that same ceiling — so a device whose clock trailed the center by more than the delivery latency turned down every grant it was handed. One observed device was 38 ms behind, and the resulting 14 ms overshoot was enough to refuse all remote connectivity. Nothing made it visible: the rejection reason was dropped, this class of refusal never rotated the serving epoch, so restarting the helper, the worker and the peer's app changed nothing, and the central path kept carrying terminal bytes, leaving the peer showing only "route offline" — which reads as a fault on the far device. The ceiling now tolerates 5 s of skew and logs why a grant was refused.
- iOS reaches devices again. Moving to Tailcat in 2.0.0 deleted the Swift client's remote transport along with the relay and WebRTC stacks, so the iOS app could log in and list devices but not open a single one. It now dials devices over the same native transport the desktop uses, with the Go transport helper linked into the app, and the link has been confirmed against a physical device. The iOS app is delivered through TestFlight and is not an artifact of this Release.
- The sidebar measures every online device, not just the one you opened. Since Tailcat became the default transport, an unselected device kept a muted dot and reported only that it was reachable through the center; its latency and its direct-or-relay path appeared only after clicking into its tab. Measurement demand is honoured on the Tailcat path again, so the sidebar reflects each online device continuously.
- The notification bell and the port menu open at full width. On astryx 0.6.0 both right-edge top-bar menus opened as a sliver a few tens of pixels wide, with every character wrapped onto its own line. They now open leftwards from the trigger and are usable again.
Install or update
Mac: install coflux-2.0.1-arm64.dmg or use the desktop app's update action. The desktop app requires macOS 26+ and Apple Silicon.
Linux or headless hosts:
npm install -g cofluxd@2.0.1
cofluxd update
cofluxd restartUpgrade impact
Upgrade the devices, not the center. No server or protocol change ships in this release; a 2.0.0 center serves 2.0.1 devices and desktops unchanged.
The clock-skew fix lives in the worker, so it reaches a device through a worker upgrade or a runtime restart. Until a device carries it, a clock that trails the center keeps every remote connection to that device offline while the central path continues to work — the symptom this release exists to remove. Devices that are already reachable need no urgency.
The sidebar and menu fixes are desktop-only and arrive with the app update.
Unchanged from 2.0.0: real internet and NAT acceptance across a reproducible network matrix, resource measurements at 0/1/10 demanded devices, and packaged GUI/keychain lifecycle acceptance remain unverified, and the loopback latency regression recorded in the 2.0.0 notes stands.
Full changelog: v2.0.0...v2.0.1
Coflux v2.0.0
Coflux 2.0.0
Remote connections now run on the Tailcat stack, and every client and device must move together.
Coflux's own relay and WebRTC signalling are gone. Desktop and headless devices reach each other over pinned Tailcat/Tailscale peer connectivity with a self-hosted stock DERP region behind it. Local loopback, the device envelope and Supervisor-owned PTYs are unchanged.
This release raises the control protocol to version 2. A client or device still speaking version 1 is refused, so this is not an upgrade that can be taken one machine at a time. Read the upgrade section before installing it.
Highlights
- Native remote transport. Peer connectivity comes from the upstream stack instead of a bespoke relay: scoped single-use channel grants, private helper IPC, direct/DERP diagnostics, bounded recovery, and fail-closed DERP admission. Worker and transport helper are verified, activated and rolled back as a pair.
- Run one command on another machine.
coflux device exec <deviceId> --cmd="…"isssh host "cmd"for the devices in your account. It is not a terminal: no PTY, nothing in the sidebar, no draw on a workspace's terminal cap, and no workspace required — a device whose directories were never registered as Coflux workspaces is still reachable. The command goes to the remotesh -c, so pipes,&&, redirection, globs and variables all work;--cwdand--timeoutbound it. - The design system is current. The desktop client moves from astryx 0.1.6 to 0.6.0 — 27 releases of upstream fixes. Same UI, newer library: no component changes its visual role and nothing is restyled beyond what the version change forces.
- The top-right actions work again. The notification bell and the port menu sat inside the terminal top bar's window drag region, which swallowed every click and hover; they are now outside it. Their tooltips also stopped appearing after the menu had been opened once, and no longer do.
Install or update
Mac: install coflux-2.0.0-arm64.dmg or use the desktop app's update action. The desktop app requires macOS 26+ and Apple Silicon.
Linux or headless hosts: upgrade the npm launcher first, then the device binaries:
npm install -g cofluxd@2.0.0
cofluxd update
cofluxd restartThe launcher upgrade is not optional. A launcher from before this release knows nothing about the transport helper: it downloads the Supervisor, Worker and CLI, reports that the Supervisor is unchanged, and leaves the device without the helper it now needs. Only a 2.0.0 launcher fetches coflux-transport alongside the rest.
Finish active work before the restart — restarting the Supervisor ends the terminal processes it owns.
Upgrade impact
Upgrade in this order. Install the desktop app and update every headless device first, then deploy the central server. A server on protocol 2 refuses every client and worker still on protocol 1; a desktop on protocol 2 shows Update Required against an older server and waits there until the server catches up. Between the two steps, one side or the other is unreachable, so plan the window rather than discovering it.
Every device needs an explicit restart. Worker hot upgrades cover the worker alone. This release changes the Supervisor and adds the transport helper beside it, and both arrive only when the runtime restarts: cofluxd restart on headless hosts, the runtime restart action on desktop. A device that is offline during the rollout stays disconnected until someone updates and restarts it.
The frozen web client and the current iOS remote paths stop working. They speak protocol 1 and are not being updated. Use the desktop app.
Latency regressed, measurably. Loopback cold attach p95 went from 7.37 ms to 25.66 ms, and warmed catalog p95 from 1.16 ms to 14.09 ms. These are loopback numbers; they say nothing about wide-area performance, which is where the new stack is meant to pay off, and that has not been measured on real networks yet.
Still unverified at release. Real internet and NAT acceptance across a reproducible network matrix, resource measurements at 0/1/10 demanded devices, and packaged GUI/keychain lifecycle acceptance. The infrastructure side — a dedicated pinned DERP region reachable over HTTPS with fail-closed admission — must be in place on the relay host and configured on the center before the server is deployed.
Full changelog: v1.2.0...v2.0.0