<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Crystal Studio</title>
    <description>The latest articles on DEV Community by Crystal Studio (@crystalstudio).</description>
    <link>https://dev.to/crystalstudio</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4097654%2Ffc0bb3d1-d5ee-43c5-9d0d-b6390f9f0898.jpg</url>
      <title>DEV Community: Crystal Studio</title>
      <link>https://dev.to/crystalstudio</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/crystalstudio"/>
    <language>en</language>
    <item>
      <title>umux v1.7.5: the switch that keeps the machine awake</title>
      <dc:creator>Crystal Studio</dc:creator>
      <pubDate>Fri, 09 Oct 2026 15:51:13 +0000</pubDate>
      <link>https://dev.to/crystalstudio/umux-v175-the-switch-that-keeps-the-machine-awake-25k2</link>
      <guid>https://dev.to/crystalstudio/umux-v175-the-switch-that-keeps-the-machine-awake-25k2</guid>
      <description>&lt;p&gt;It has been a short cycle this time. One feature, the one the last post ended on.&lt;/p&gt;

&lt;p&gt;Landing: &lt;a href="https://umux.pages.dev" rel="noopener noreferrer"&gt;https://umux.pages.dev&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/CrystalPlatforms/umux" rel="noopener noreferrer"&gt;https://github.com/CrystalPlatforms/umux&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;umux is a free, open-source terminal workspace manager for Linux, Windows and macOS. One workspace per project, tabs inside it, every tab splitting into as many panels as you need. The idea the app is built around: umux reads the completion signals that AI CLIs emit when a long task finishes, and turns them into a desktop notification.&lt;/p&gt;

&lt;p&gt;v1.7.0 moved the sessions out of the window: a daemon owns them, so closing the app no longer ends the work. One hole stayed open. The OS itself could still end everything, because a machine that falls asleep takes its agents with it. v1.7.5 closes that hole. The switch is umux Core, the Always-On device. The name used to belong to the daemon in its early days; the daemon is Storestation now, and the feature took the name back.&lt;/p&gt;

&lt;h2&gt;
  
  
  The switch
&lt;/h2&gt;

&lt;p&gt;Core lives in Settings, off by default, and off means exactly what it meant before. Switch it on and the daemon holds the machine awake. The screen may still sleep and lock. Locking a screen stops nothing, so what stays up is the machine: the enemy is the suspend, and the suspend is what killed the agent.&lt;/p&gt;

&lt;p&gt;The daemon is the same one that already owns the sessions, and that choice is the feature. A hold owned by the app would die with the windows, and the whole point is windows being closed. Owned by the daemon, it survives every window closing, comes back on its own after a restart, and needs no app anywhere in the loop.&lt;/p&gt;

&lt;h2&gt;
  
  
  What each system admits
&lt;/h2&gt;

&lt;p&gt;This is the part I care about most. A sleep-blocker that does its job in silence is worse than no switch at all, because you plan an evening around a promise that was never made. So every limit ships in words, in Settings and in &lt;code&gt;umux status --json&lt;/code&gt;, on every platform.&lt;/p&gt;

&lt;p&gt;On macOS the hold is the strong kind: machine up, lid closed included, while plugged in. On battery the system may refuse it, so umux says exactly that. On Windows the hold stops idle sleep; the lid-close action belongs to the power plan, a system setting an app has no business rewriting, so umux shows you where it lives instead. Linux is the same shape: the session inhibitor stops idle suspend, the lid stays the system's own business, and status says so. Three platforms, three different refusals.&lt;/p&gt;

&lt;p&gt;One rule carries all of it: when the promise has a hole, umux names the hole.&lt;/p&gt;

&lt;h2&gt;
  
  
  The hold dies with its holder
&lt;/h2&gt;

&lt;p&gt;The block is not a flag parked somewhere in the system. It lives inside the daemon's process, so ending that process ends it. Toggle Core off and it releases. Stop the daemon and it releases too. Kill the process outright and the OS takes the hold back on its own, because there was never a second copy of it anywhere. There is no path to a machine kept awake by a ghost.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shipping
&lt;/h2&gt;

&lt;p&gt;It rides in the five regular installers: the .deb, the .AppImage, the .rpm, the NSIS installer and the universal .dmg. Switching Core on never means a second download, and an app update replaces it together with the app. Free, MIT, no accounts.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest list
&lt;/h2&gt;

&lt;p&gt;macOS on battery is best effort: plug in for the real promise. The lid on Windows and Linux stays the system's setting, and umux points at it rather than touching it. Import from cmux still does not work on Windows. X11 sessions are untested; Wayland is the reference.&lt;/p&gt;

&lt;p&gt;Landing: &lt;a href="https://umux.pages.dev" rel="noopener noreferrer"&gt;https://umux.pages.dev&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/CrystalPlatforms/umux" rel="noopener noreferrer"&gt;https://github.com/CrystalPlatforms/umux&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cli</category>
      <category>opensource</category>
      <category>software</category>
      <category>tools</category>
    </item>
    <item>
      <title>umux 1.7.0: close the window, keep the work</title>
      <dc:creator>Crystal Studio</dc:creator>
      <pubDate>Fri, 02 Oct 2026 19:49:29 +0000</pubDate>
      <link>https://dev.to/crystalstudio/umux-170-close-the-window-keep-the-work-4bll</link>
      <guid>https://dev.to/crystalstudio/umux-170-close-the-window-keep-the-work-4bll</guid>
      <description>&lt;p&gt;It has been quiet here for two weeks. This release is what the quiet went into.&lt;/p&gt;

&lt;p&gt;Landing: &lt;a href="https://umux.pages.dev" rel="noopener noreferrer"&gt;https://umux.pages.dev&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/CrystalPlatforms/umux" rel="noopener noreferrer"&gt;https://github.com/CrystalPlatforms/umux&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;umux is a free, open-source terminal workspace manager for Linux, Windows and macOS. One workspace per project, tabs inside it, and every tab splits into as many panels as you need. The feature the app is built around: umux reads the OSC 9;9, 99 and 777 escape sequences that AI CLIs like Claude Code emit when a long task finishes, and turns them into a desktop notification.&lt;/p&gt;

&lt;p&gt;v1.6.2 taught the app to notice when an agent stops mid-task. v1.7.0 ships the thing the last post promised and deferred: a daemon that lets sessions outlive the window. The last release note ended on "it can wait". It couldn't wait: the daemon that post called Core ships as umux Storestation.&lt;/p&gt;

&lt;h2&gt;
  
  
  The daemon
&lt;/h2&gt;

&lt;p&gt;Off by default, and off is exactly v1.6.x: the app owns its shells, closing it ends them, byte for byte the old behavior. Switch Storestation on in Settings and ownership moves. A small headless binary serves one local socket and owns every session. The desktop app becomes a view on work that lives outside it: close every window and the shells keep running, an agent halfway through a task keeps going, and the output keeps growing into a scrollback you can read later.&lt;/p&gt;

&lt;p&gt;Settings keeps its main page short. umux Storestation is one entry there; opening it swaps the whole page for just the two switches, daemon and autostart, plus the live status line. Factory reset got the same room, so the main page stays a list of doors instead of a wall of switches.&lt;/p&gt;

&lt;h2&gt;
  
  
  attach
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;umux attach&lt;/code&gt; is the way back. Run it from a terminal and it launches the app bound to the daemon's living sessions, or focuses the one already open. An offline daemon is an honest failure: attach explains that nothing is running and exits. The whole point is coming back after minutes or hours and finding the work where you left it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The headless surface
&lt;/h2&gt;

&lt;p&gt;The CLI drives Storestation with no window anywhere in the loop:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;umux status&lt;/code&gt; answers with the daemon's health. Offline is a state, not an error: it exits 0 and says so.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;umux status --json&lt;/code&gt; gives the machine-readable document: running, version, pid, uptime, sessions, attached clients.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;umux sessions list&lt;/code&gt; prints the live sessions the daemon owns.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;umux agent-context&lt;/code&gt; describes the CLI itself as data, so scripts can discover the surface instead of parsing help text.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Exit codes follow one catalog across both binaries: 0 ok or offline, 2 usage, 3 unreachable, 4 already running, 5 internal. A second daemon refuses to start with that 4 instead of half-starting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lifecycle discipline
&lt;/h2&gt;

&lt;p&gt;Three rules carry the whole design. A clean stop terminates every owned shell, so stopping the daemon never leaves orphan processes behind. A hard kill does leave a trail, and the next start detects the leftovers and sweeps them. And the socket decides liveness, never the pid file, so a crashed daemon's stale files cannot fake a running one.&lt;/p&gt;

&lt;p&gt;Autostart at login ships natively per platform: a systemd user unit on Linux, a LaunchAgent on macOS, and a Run key on Windows that launches with a hidden console, because a console binary launched at login would flash a window on every boot.&lt;/p&gt;

&lt;h2&gt;
  
  
  It ships in the installers
&lt;/h2&gt;

&lt;p&gt;Enabling Storestation never means installing something extra. All five packages, the .deb, the .AppImage, the .rpm, the NSIS installer and the universal .dmg, carry the daemon beside the CLI. The macOS PATH line covers both binaries, the Linux package drops it in /usr/bin, and the plain-CLI install script installs it too. An app update replaces the daemon together with the app: one version number for the whole workspace, and &lt;code&gt;umux status&lt;/code&gt; reports it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The storefront shows the real thing
&lt;/h2&gt;

&lt;p&gt;The landing page spent the release with grey placeholders standing in for screenshots. They are gone. Four real shots are in, one per feature tile: workspaces, the terminal, the updates settings, the cmux import wizard. The SSH tile took a different road: rather than ship a stand-in image, it goes without one, at the end of the feature list. A placeholder on a public page is a promise to fix later, and later had arrived.&lt;/p&gt;

&lt;h2&gt;
  
  
  The numbers
&lt;/h2&gt;

&lt;p&gt;Twenty-three commits since the last post, 134 files, about 12,100 lines added and 5,100 removed. The frontend suite sits at 739 passing tests. The Rust side runs 282 of them across 21 suites, most of them new in this release: protocol, lifecycle hardening, reattach, live session lists, attach resolution.&lt;/p&gt;

&lt;p&gt;The installers: .deb, .AppImage and .rpm on Linux, a universal .dmg on macOS 11+, an NSIS installer on Windows 10+. MIT licensed, no accounts. The in-app updater picks 1.7.0 up on its own.&lt;/p&gt;

&lt;p&gt;Landing: &lt;a href="https://umux.pages.dev" rel="noopener noreferrer"&gt;https://umux.pages.dev&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/CrystalPlatforms/umux" rel="noopener noreferrer"&gt;https://github.com/CrystalPlatforms/umux&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>umux 1.6.2: ping me when you're stuck</title>
      <dc:creator>Crystal Studio</dc:creator>
      <pubDate>Tue, 15 Sep 2026 19:06:38 +0000</pubDate>
      <link>https://dev.to/crystalstudio/umux-162-ping-me-when-youre-stuck-5181</link>
      <guid>https://dev.to/crystalstudio/umux-162-ping-me-when-youre-stuck-5181</guid>
      <description>&lt;p&gt;umux is a free, open-source terminal workspace manager for Linux, Windows and macOS. One workspace per project, tabs inside it, and every tab splits into as many panels as you need. The feature the app is built around: umux reads the OSC 9;9, 99 and 777 escape sequences that AI CLIs like Claude Code emit when a long task finishes, and turns them into a desktop notification.&lt;/p&gt;

&lt;p&gt;Landing: &lt;a href="https://umux.pages.dev" rel="noopener noreferrer"&gt;https://umux.pages.dev&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/CrystalPlatforms/umux" rel="noopener noreferrer"&gt;https://github.com/CrystalPlatforms/umux&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;v1.6.0 taught the app to ask which shell you use. v1.6.2 teaches it to notice when your agent stops mid-task and waits for you. The release hangs on one gap: until now the bell rang only at the finish line, and agents spend much of their time before it, parked on a permission prompt nobody announced.&lt;/p&gt;

&lt;h2&gt;
  
  
  The ping for waiting agents
&lt;/h2&gt;

&lt;p&gt;umux tracks a status per panel: working, needs-attention, or nothing. The flip from working to needs-attention used to be a silent one. In 1.6.2 it rings the same bell a finished task does, under the same single Desktop notifications switch.&lt;/p&gt;

&lt;p&gt;A gate keeps it to one ping per waiting session. Terminal UIs repaint on a cycle, and the flip can happen every ten seconds during a repaint. Without the gate you would get rung every ten seconds. With it you get rung once, and the next ping waits for a genuinely new wait.&lt;/p&gt;

&lt;h2&gt;
  
  
  Click through to the panel
&lt;/h2&gt;

&lt;p&gt;A notification that tells you something happened is good. A notification that takes you there is better. The banner carries its workspace, tab and panel, and clicking it navigates straight to the panel the agent sits in. Linux hangs an Open action on the banner. macOS and Windows route a focus heuristic that stays valid for 60 seconds after the ping.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quiet is an answer too
&lt;/h2&gt;

&lt;p&gt;The end of a wait is not always announced. CLIs without completion escapes never say they are done; they stop talking. After you answer, a reply that streams and then goes quiet now drops the panel back to needs-attention after 10 seconds of silence, down from about 60.&lt;/p&gt;

&lt;h2&gt;
  
  
  Windows: folder lines go live
&lt;/h2&gt;

&lt;p&gt;The sidebar's folder lines work on Windows now, live. Reading another process's working directory there means reading its PEB. And PowerShell never syncs its own process cwd when you cd, so umux chains a prompt hook that syncs the working directory and emits the OSC 9;9 report, without ever overwriting the prompt you see. cmd gets the same through a PROMPT override. The parser surfaces those reports with the byte stream untouched, and the sidebar folds a folder change in instantly, ahead of the 20-second snapshot. SSH panels ignore the reports: a remote path is not a local cwd.&lt;/p&gt;

&lt;h2&gt;
  
  
  A tooltip that answers in time
&lt;/h2&gt;

&lt;p&gt;The ports tooltip on Windows used to spawn a PowerShell query per hover, about 0.6 seconds, and the answer landed after your cursor had left the row. It reads a Toolhelp32 snapshot now, about 10 ms. The answer arrives while you are still looking at it.&lt;/p&gt;

&lt;p&gt;One more from daily use: a new tab inherits the folder of the tab you were on. SSH tabs and session restore keep their own rules.&lt;/p&gt;

&lt;h2&gt;
  
  
  The sidebar keeps its width
&lt;/h2&gt;

&lt;p&gt;The honest list in the last post said drag-to-resize worked on macOS only. This release closes that line. The width persists across restarts on all three operating systems, saved on drag release and again 400 ms after the last move, because release events do not always arrive. A restored width clamps to the live window's limits.&lt;/p&gt;

&lt;p&gt;Folder lines learned to merge in the same pass. With agent status on, every tab keeps its own line and its own chip. With agent status off, tabs sharing a folder share one line, drawn at the first of them. Lines without a folder never merge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Small things
&lt;/h2&gt;

&lt;p&gt;The app boots behind a splashscreen now, and the main window appears with a two-second beat so the splash is actually seen.&lt;/p&gt;

&lt;h2&gt;
  
  
  The numbers
&lt;/h2&gt;

&lt;p&gt;The app-side diff is 26 files: about 2,600 lines added and 240 removed. The frontend suite sits at 739 passing tests, up from 700 at v1.6.1. The growth is mostly new suites: the waiting-ping gate and its decay, notification routing, folder-line merging, and the new-tab inheritance.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest list
&lt;/h2&gt;

&lt;p&gt;Import from cmux still does not work on Windows. X11 sessions are untested; Wayland is the reference platform. Agent status took its biggest step in this release and still has edges to sand.&lt;/p&gt;

&lt;p&gt;The installers: .deb, .AppImage and .rpm on Linux, a universal .dmg on macOS 11+, an NSIS installer on Windows 10+. MIT licensed, no accounts. The in-app updater picks 1.6.2 up on its own.&lt;/p&gt;

&lt;p&gt;Landing: &lt;a href="https://umux.pages.dev" rel="noopener noreferrer"&gt;https://umux.pages.dev&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/CrystalPlatforms/umux" rel="noopener noreferrer"&gt;https://github.com/CrystalPlatforms/umux&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
      <category>opensource</category>
    </item>
    <item>
      <title>umux 1.6: Any Shell in Any Tab</title>
      <dc:creator>Crystal Studio</dc:creator>
      <pubDate>Thu, 10 Sep 2026 18:36:22 +0000</pubDate>
      <link>https://dev.to/crystalstudio/umux-16-any-shell-in-any-tab-4542</link>
      <guid>https://dev.to/crystalstudio/umux-16-any-shell-in-any-tab-4542</guid>
      <description>&lt;p&gt;umux is a free, open-source terminal workspace manager for Linux, Windows and macOS. One workspace per project, tabs inside it, and every tab splits into as many panels as you need. The feature the app is built around: umux reads the OSC 9;9, 99 and 777 escape sequences that AI CLIs like Claude Code emit when a long task finishes, and turns them into a desktop notification.&lt;/p&gt;

&lt;p&gt;Landing: &lt;a href="https://umux.pages.dev" rel="noopener noreferrer"&gt;https://umux.pages.dev&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/CrystalPlatforms/umux" rel="noopener noreferrer"&gt;https://github.com/CrystalPlatforms/umux&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The last four releases were repairs. v1.5.2 smoothed Windows, v1.5.3 fixed five things on macOS, v1.5.4 killed a bug every packaged build had carried since the first one. v1.6.0 is the release in this streak that only adds.&lt;/p&gt;

&lt;h2&gt;
  
  
  The shell picker
&lt;/h2&gt;

&lt;p&gt;New tabs open in your default shell, and until now that default was whatever your operating system decided. Settings asks you properly in 1.6.0: pick from the shells detected on your machine, or type a custom command for anything the detector misses.&lt;/p&gt;

&lt;p&gt;Detection needs no setup. A PATH scan backs the list on all three systems. On Unix it reads /etc/shells and your login-shell record, so bash, zsh and fish show up as themselves. On Windows it checks the registry, and WSL distros land in the list next to PowerShell, cmd and Git Bash.&lt;/p&gt;

&lt;h2&gt;
  
  
  One arrow, and only when it means something
&lt;/h2&gt;

&lt;p&gt;The "+ New tab" button grows a small arrow. It opens a dropdown that spawns one tab in a different shell, leaving your default alone. Spawn a fish tab to test a config, keep working in zsh.&lt;/p&gt;

&lt;p&gt;The arrow obeys one rule: it exists only when there is a real choice. A machine with a single installed shell shows no arrow at all, because a dropdown with one item is noise. The picker affects local tabs only; SSH sessions keep the remote machine's login shell, exactly as before.&lt;/p&gt;

&lt;h2&gt;
  
  
  The sidebar, on your terms
&lt;/h2&gt;

&lt;p&gt;Two switches ship in Settings, both off by default.&lt;/p&gt;

&lt;p&gt;The first hides the git branch on tab rows, for the days you want the sidebar quiet. The second lists working directories on workspace rows: one line per tab, that tab's agent-status chip next to the folder its shell sits in. Every tab gets a line and duplicates stay unmerged. The data comes from the directories umux already tracks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Small things
&lt;/h2&gt;

&lt;p&gt;Tabs go full screen, and ESC brings them back. The accent rails on workspace and tab rows now run the full row length in a straight line. The Settings dialog title is larger. All three came out of using the app daily.&lt;/p&gt;

&lt;h2&gt;
  
  
  The numbers
&lt;/h2&gt;

&lt;p&gt;Twelve commits since v1.5.4. The diff adds about 3,800 lines and removes 200 across 41 files. Six new modules ride along: the shell detector with its test suite, the per-tab folder model with its own tests, and the Rust-side shell probe. The frontend suite sits at 698 passing tests, up from 616 at v1.5.4.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest list
&lt;/h2&gt;

&lt;p&gt;Import from cmux still does not work on Windows. X11 sessions are untested; Wayland is the reference platform. Agent status is still the roughest feature in the app. The sidebar's drag-to-resize gesture works on macOS only so far; the cross-platform fix with a persisted width is queued for a small v1.6.1 patch. After that comes the big rock: the umux Core daemon.&lt;/p&gt;

&lt;p&gt;The installers: .deb, .AppImage and .rpm on Linux, a universal .dmg on macOS 11+, an NSIS installer on Windows 10+. MIT licensed, no accounts, and one anonymous app-open event is the entire telemetry. The in-app updater picks 1.6.0 up on its own.&lt;/p&gt;

&lt;p&gt;Landing: &lt;a href="https://umux.pages.dev" rel="noopener noreferrer"&gt;https://umux.pages.dev&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/CrystalPlatforms/umux" rel="noopener noreferrer"&gt;https://github.com/CrystalPlatforms/umux&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cli</category>
      <category>opensource</category>
      <category>software</category>
      <category>terminal</category>
    </item>
    <item>
      <title>Four releases, five days, one phantom that hid behind a minified name</title>
      <dc:creator>Crystal Studio</dc:creator>
      <pubDate>Mon, 07 Sep 2026 12:47:01 +0000</pubDate>
      <link>https://dev.to/crystalstudio/four-releases-five-days-one-phantom-that-hid-behind-a-minified-name-6ok</link>
      <guid>https://dev.to/crystalstudio/four-releases-five-days-one-phantom-that-hid-behind-a-minified-name-6ok</guid>
      <description>&lt;p&gt;umux is a free, open-source terminal workspace manager for Linux, Windows and macOS. One workspace per project, tabs inside it, and every tab splits into as many panels as you need. The feature the app is built around: umux reads the OSC 9;9, 99 and 777 escape sequences that AI CLIs like Claude Code emit when a long task finishes, and turns them into a desktop notification.&lt;/p&gt;

&lt;p&gt;Landing: &lt;a href="https://umux.pages.dev" rel="noopener noreferrer"&gt;https://umux.pages.dev&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/CrystalPlatforms/umux" rel="noopener noreferrer"&gt;https://github.com/CrystalPlatforms/umux&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This covers four releases in five days. v1.5.1 gave workspaces colors and taught the cmux import to carry them over. v1.5.2 was the Windows smoothness pass. v1.5.3 fixed five things on macOS. And v1.5.4 killed the bug this release is named after: a terminal that worked in every dev build and died in every packaged one.&lt;/p&gt;
&lt;h2&gt;
  
  
  v1.5.2: what it takes to stop a terminal from stuttering
&lt;/h2&gt;

&lt;p&gt;The Windows build passed every test and felt bad anyway. Output stuttered while a command streamed. Empty console windows flashed on hover. Four causes, four fixes.&lt;/p&gt;

&lt;p&gt;PTY bytes crossed to the WebView as a JSON array of numbers, so one byte became up to four characters of JSON. They travel as base64 now, four times smaller, one decode on arrival. OS work ran on the UI thread: process lookups, working directories, listening ports, git branches, store saves. All of it is asynchronous now, and the PTY mutex is held only long enough to read a pid. The foreground-process lookup spawned tasklist.exe per check; it is one call to OpenProcess plus QueryFullProcessImageNameW now. And every shell-out passes CREATE_NO_WINDOW now: netstat, the PowerShell CIM queries, the toast notifier. The phantom console windows are gone.&lt;/p&gt;

&lt;p&gt;The terminal also renders through xterm.js's WebGL addon since this release, with a fallback to the DOM renderer if the GPU context dies.&lt;/p&gt;
&lt;h2&gt;
  
  
  v1.5.3: five fixes from one macOS report
&lt;/h2&gt;

&lt;p&gt;One report turned into five fixes. The WebGL addon renders a black canvas on Apple WebKit and WebKitGTK: the context creates fine and presents nothing. It loads on Chromium-based webviews only now, with the DOM renderer everywhere else. A GUI-launched app has no $SHELL, so panels ran /bin/sh and loaded none of your config; the shell resolves through getpwuid now. The bare &lt;code&gt;monospace&lt;/code&gt; font renders Courier in WKWebView; the stack is ui-monospace/Menlo/Consolas/DejaVu. A dead working directory fell back to the app's own cwd instead of your home. And a relative "." from lsof no longer gets stored as a panel directory.&lt;/p&gt;
&lt;h2&gt;
  
  
  v1.5.4: works in dev, black in production
&lt;/h2&gt;

&lt;p&gt;Then the report this release is named after. Third-party CLIs like Mistral Vibe and OpenCode start inside umux, and the panel goes black. Claude Code runs fine. Typing feels dead. Closing the tab is the only way out.&lt;/p&gt;

&lt;p&gt;The first suspect was ours and wrong. The OSC parser really did eat Kitty notification queries (&lt;code&gt;ESC]99;…p=?&lt;/code&gt;) and really did mistake ConEmu progress reports (&lt;code&gt;ESC]9;4;…&lt;/code&gt;) for task completions. Both fixed. The phantom "4;0;" notifications from Claude Code panels stopped. But byte captures showed the TUI stream passing through the backend intact, so the loss lived between the IPC bridge and the pixels.&lt;/p&gt;

&lt;p&gt;Instrumentation came next: an opt-in, flag-file-gated dump that logs byte counts per chunk and DOM character counts per panel. Numbers only, never terminal content. It showed something that made no sense: the bytes arrived, the DOM held the TUI's text, and the screen stayed black. That pushed the hunt toward compositing theories. All of them were wrong.&lt;/p&gt;

&lt;p&gt;What cracked it was a harness. The real production bundle, served the way the packaged app serves it, a mocked IPC layer, and a recorded byte stream replayed into real WebKit. The black screen reproduced in minutes, and the console held the answer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;ReferenceError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;defined&lt;/span&gt;
 &lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="nx"&gt;requestMode&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;xterm.js 6.0.0 ships pre-minified. Inside its requestMode handler, a closure captures a parameter, and an enum initializes through a polyfill pattern. Vite's build step re-minifies that code a second time, the names stop existing, and the first mode query a modern TUI sends at startup throws. That query is &lt;code&gt;ESC[?2026$p&lt;/code&gt;, the synchronized-output probe. The exception kills xterm's write worker. Nothing renders after it. Nothing you type changes what you see.&lt;/p&gt;

&lt;p&gt;Upstream issue xtermjs/xterm.js#5800 describes this bug word for word, down to the console line. Another terminal project hit the same crash. The fix ships with umux as a patch-package patch: the enum polyfill becomes a plain object, and the flag moves into a local constant before any closure can capture it. &lt;code&gt;npm install&lt;/code&gt; applies the patch, and a contract test locks the synchronized-output paint behavior in place.&lt;/p&gt;

&lt;p&gt;The same release paints DEC 2026 frames the moment their block closes. xterm otherwise debounces the paint into a window the next frame's sync block can invalidate, which freezes a fast full-screen TUI to about one frame per second. And the diagnostics mode stays in the build, flag-gated, for whoever hunts the next ghost.&lt;/p&gt;

&lt;h2&gt;
  
  
  The numbers
&lt;/h2&gt;

&lt;p&gt;Four releases. v1.5.4 lands as +779/−28 across eight files plus the xterm patch. The frontend suite sits at 616 passing tests, the Rust suite at 97, plus a WebKit harness that runs the real bundle against a recorded stream. That check would have caught this bug before any user did.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest list
&lt;/h2&gt;

&lt;p&gt;Import from cmux still does not work on Windows. X11 sessions are untested; Wayland is the reference platform. Agent status is still the roughest feature in the app. The umux Terminal TUI, with the herdr importer, is the next big rock. Planned for v1.7.&lt;/p&gt;

&lt;p&gt;The installers: .deb, .AppImage and .rpm on Linux, a universal .dmg on macOS 11+, an NSIS installer on Windows 10+. MIT licensed, no accounts, and one anonymous app-open event is the entire telemetry.&lt;/p&gt;

&lt;p&gt;Landing: &lt;a href="https://umux.pages.dev" rel="noopener noreferrer"&gt;https://umux.pages.dev&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/CrystalPlatforms/umux" rel="noopener noreferrer"&gt;https://github.com/CrystalPlatforms/umux&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If a terminal inside umux ever went black on you: v1.5.4 is the one to install.&lt;/p&gt;

</description>
      <category>cli</category>
      <category>opensource</category>
      <category>showdev</category>
      <category>terminal</category>
    </item>
    <item>
      <title>Every workspace in umux gets a color now, and cmux colors come with you</title>
      <dc:creator>Crystal Studio</dc:creator>
      <pubDate>Sat, 05 Sep 2026 06:29:40 +0000</pubDate>
      <link>https://dev.to/crystalstudio/every-workspace-in-umux-gets-a-color-now-and-cmux-colors-come-with-you-3a61</link>
      <guid>https://dev.to/crystalstudio/every-workspace-in-umux-gets-a-color-now-and-cmux-colors-come-with-you-3a61</guid>
      <description>&lt;p&gt;umux is a free, open-source terminal workspace manager for Linux, Windows and macOS. One workspace per project, tabs inside it, and every tab splits into as many panels as you need. The feature the app is built around: umux reads the OSC 9;9, 99 and 777 escape sequences that AI CLIs like Claude Code emit when a long task finishes, and turns them into a desktop notification.&lt;/p&gt;

&lt;p&gt;Landing: &lt;a href="https://umux.pages.dev" rel="noopener noreferrer"&gt;https://umux.pages.dev&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/CrystalPlatforms/umux" rel="noopener noreferrer"&gt;https://github.com/CrystalPlatforms/umux&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The last post here covered v1.0.2 through v1.0.4: the cmux importer, in-app updates, and the offline CLI. Today's release is v1.5.1. Eight commits, about two thousand lines added, and one idea carrying the release: color.&lt;/p&gt;

&lt;h2&gt;
  
  
  The gray-objects problem
&lt;/h2&gt;

&lt;p&gt;Every row in a terminal manager's sidebar is text. With six projects open, telling them apart means reading, every time, in the sidebar and in the tab bar. v1.5.1 lets each workspace carry a color instead. There are eight, chosen from the workspace's context menu.&lt;/p&gt;

&lt;p&gt;The color shows up in small places. A square swatch sits beside the workspace name, and a colored edge runs down the left side of the app while that workspace is active. Tabs get the same treatment: a swatch in the tab bar and a colored strip along the top edge while the tab is active. Groups tint their folder icon. A pinned workspace wears its color on the pin, because the pin is the one mark that is always visible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your cmux colors come with you
&lt;/h2&gt;

&lt;p&gt;The part I like most is what happens on import. cmux stores an accent color per workspace and per group as free-form hex: whatever you picked, sixteen million options. umux has a fixed palette of eight. The importer maps every cmux color to the nearest palette entry by squared RGB distance, and the setup arrives looking the way it looked before. Not exactly the same. Nearest.&lt;/p&gt;

&lt;p&gt;The mapping is strict on purpose. Only a well-formed &lt;code&gt;#RRGGBB&lt;/code&gt; string maps to a palette entry; anything else imports as no color at all. A wrong guess sits in your sidebar forever, but gray costs two clicks to fix.&lt;/p&gt;

&lt;p&gt;One detail only shows up when you read cmux's files closely: the actions in cmux.json carry no colors. The session store is the only place colors live, so it is the only place the importer reads them from.&lt;/p&gt;

&lt;h2&gt;
  
  
  One import, two implementations, one suite
&lt;/h2&gt;

&lt;p&gt;The color mapping exists twice, like everything in the importer: TypeScript in the in-app wizard, Rust in the &lt;code&gt;umux import cmux&lt;/code&gt; CLI. The golden-fixture parity suite keeps both honest — the fixtures of cmux state now carry color cases, and one expected plan says exactly which palette entry each maps to. If the two implementations drift, a test goes red before either ships a wrong color. &lt;code&gt;umux import cmux --dry-run&lt;/code&gt; still prints the plan and writes nothing; the plan carries the mapped colors, so you can read where everything landed before anything lands.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ports you can click
&lt;/h2&gt;

&lt;p&gt;The ports tooltip has always listed which local ports your dev servers are listening on. Now a click on a port opens &lt;code&gt;http://localhost:PORT&lt;/code&gt; in your browser. The URL still lands on your clipboard too, because copy-on-click is muscle memory nobody should have to unlearn. The new dependency doing the opening is tauri-plugin-opener.&lt;/p&gt;

&lt;h2&gt;
  
  
  The small stuff
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The inline rename pencil is gone from workspace and group rows. Renaming lives in the context menu — one place, not two.&lt;/li&gt;
&lt;li&gt;The × next to a workspace now deletes it, behind a confirmation. It used to just close it, which read like deleting and wasn't.&lt;/li&gt;
&lt;li&gt;Settings has a &lt;strong&gt;Reset umux&lt;/strong&gt; button. Two clicks wipe every state file (workspaces, layouts, settings) and the app relaunches into its first-run state. A factory reset for when an experiment goes wrong.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  About the version number
&lt;/h2&gt;

&lt;p&gt;v1.5.1 follows v1.0.4 directly. The jump is bookkeeping: the roadmap's version numbers got renumbered so the roadmap and the shipped tags stay in step. The app just carried on.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest list
&lt;/h2&gt;

&lt;p&gt;Import still does not work on Windows, same as in the first post. X11 sessions are untested; Wayland is the reference platform. Agent status is still the roughest feature in the app, and the completion notification is still the solid part.&lt;/p&gt;

&lt;p&gt;Between the last post and this one: 8 commits, +2,127/−192 lines, roughly 950 of them new test code. The installers: .deb, .AppImage and .rpm on Linux, a universal .dmg on macOS 11+, an NSIS installer on Windows 10+. MIT licensed, no accounts, and one anonymous app-open event is the entire telemetry.&lt;/p&gt;

&lt;p&gt;Landing: &lt;a href="https://umux.pages.dev" rel="noopener noreferrer"&gt;https://umux.pages.dev&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/CrystalPlatforms/umux" rel="noopener noreferrer"&gt;https://github.com/CrystalPlatforms/umux&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you color your workspaces in cmux and assumed a switch meant repainting everything by hand: it doesn't. Run the dry run and read the mapped palette before anything moves.&lt;/p&gt;

</description>
      <category>cli</category>
      <category>opensource</category>
      <category>software</category>
      <category>terminal</category>
    </item>
    <item>
      <title>We built a free terminal manager for 3 platforms. Four days later it imports cmux setups</title>
      <dc:creator>Crystal Studio</dc:creator>
      <pubDate>Tue, 01 Sep 2026 17:37:52 +0000</pubDate>
      <link>https://dev.to/crystalstudio/we-built-a-free-terminal-manager-for-3-platforms-four-days-later-it-imports-cmux-setups-3if</link>
      <guid>https://dev.to/crystalstudio/we-built-a-free-terminal-manager-for-3-platforms-four-days-later-it-imports-cmux-setups-3if</guid>
      <description>&lt;p&gt;v1.0.2 shipped on August 27. It was the first release with native builds for all three platforms. Four days later the tree sits at v1.0.4, with 26 commits and two releases in a single day behind it. Here is what went in.&lt;/p&gt;

&lt;p&gt;Landing: &lt;a href="https://umux.pages.dev" rel="noopener noreferrer"&gt;https://umux.pages.dev&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/CrystalPlatforms/umux" rel="noopener noreferrer"&gt;https://github.com/CrystalPlatforms/umux&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The first feature after launch was a door out of cmux
&lt;/h2&gt;

&lt;p&gt;cmux is the closest project to umux, and a good one: macOS only. Launching a cross-platform alternative and waiting for people to switch is the obvious move. But switching means rebuilding your workspace setup by hand, and my bet is that cost kills more migrations than missing features do. So the importer came first.&lt;/p&gt;

&lt;p&gt;It reads cmux's state strictly read-only and builds a plan: workspaces, groups, sidebar order, working dirs, tabs. You preview the plan before anything lands. &lt;code&gt;umux import cmux --dry-run&lt;/code&gt; prints the resolved tree and writes nothing. Name collision? Nothing gets overwritten. "api" becomes "api from cmux". Taken too? "api from cmux 2".&lt;/p&gt;

&lt;p&gt;Two implementations exist. The in-app wizard is TypeScript, the CLI command is Rust. A parity suite keeps them honest: golden JSON fixtures of cmux state, one expected plan, and a test that goes red the moment the two drift apart.&lt;/p&gt;
&lt;h2&gt;
  
  
  The app updates itself, for $0
&lt;/h2&gt;

&lt;p&gt;v1.0.3 added in-app updates. The app checks at startup, and one click downloads, verifies and relaunches. The update bundles carry a minisign signature, and the app verifies them before install. The installers themselves stay unsigned. Code-signing certificates cost money, and this project's whole budget is $0. Same for the update server: it is GitHub Releases. The free CDN that serves the installers also serves &lt;code&gt;latest.json&lt;/code&gt; to every running copy.&lt;/p&gt;
&lt;h2&gt;
  
  
  The CLI rides in every installer
&lt;/h2&gt;

&lt;p&gt;v1.0.4 put the umux CLI on PATH in every installer, Windows included. It works offline against the same store the app uses. &lt;code&gt;umux list&lt;/code&gt; prints your workspaces as JSON, &lt;code&gt;umux new&lt;/code&gt;, &lt;code&gt;rm&lt;/code&gt;, &lt;code&gt;rename&lt;/code&gt; and &lt;code&gt;split&lt;/code&gt; edit them, and &lt;code&gt;umux export&lt;/code&gt; writes a neutral backup format. One more: &lt;code&gt;umux notify&lt;/code&gt; shows a desktop notification with the app closed. Your cron jobs can use it too.&lt;/p&gt;
&lt;h2&gt;
  
  
  curl | sh, with a test suite
&lt;/h2&gt;

&lt;p&gt;The newest piece is install.sh. One line on macOS or Linux:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/CrystalPlatforms/umux/main/install.sh | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;213 lines of POSIX sh. There is no jq dependency; the script parses the GitHub API response with sed. On macOS it mounts the universal .dmg and copies the binary out of the app bundle. On Linux it opens the .deb in place with ar and tar and extracts &lt;code&gt;usr/bin/umux&lt;/code&gt;. Nothing lands outside the install directory (&lt;code&gt;~/.local/bin&lt;/code&gt; by default).&lt;/p&gt;

&lt;p&gt;The odd part: the script has its own Vitest suite. 102 lines that invoke &lt;code&gt;sh install.sh --dry-run&lt;/code&gt; the same way a user's pipe would, kept deterministic through the script's own environment hooks so the tests never touch the network. One test guards a real gotcha: release tags are v-prefixed (&lt;code&gt;v1.0.4&lt;/code&gt;) and asset filenames are not (&lt;code&gt;umux_1.0.4_universal.dmg&lt;/code&gt;), so a user pinning either form must land on the same file. The real download path got verified by hand on macOS against v1.0.4. Both the .dmg mount and the .deb extraction produce a working &lt;code&gt;umux --version&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Also landed
&lt;/h2&gt;

&lt;p&gt;Workspaces nest into groups now: a tree in the sidebar, drag &amp;amp; drop, multi-select, and a collapsed-group badge that shows how its AI agents are doing. The landing page got a proper install section and a new logo. Tests: 722 across frontend and Rust, up from 449 at launch, all green on today's HEAD.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest list
&lt;/h2&gt;

&lt;p&gt;Import does not work on Windows yet. Agent status (working, needs attention, idle) is the roughest feature in the app; the completion notification is the solid part. X11 sessions are untested; Wayland is the reference platform.&lt;/p&gt;

&lt;p&gt;The app itself: .deb, .AppImage and .rpm on Linux, a universal .dmg on macOS 11+, an NSIS installer on Windows 10+. MIT licensed, no accounts, and one anonymous app-open event is the entire telemetry.&lt;/p&gt;

&lt;p&gt;Landing: &lt;a href="https://umux.pages.dev" rel="noopener noreferrer"&gt;https://umux.pages.dev&lt;/a&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/CrystalPlatforms/umux" rel="noopener noreferrer"&gt;https://github.com/CrystalPlatforms/umux&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you run cmux on a Mac and ever wondered what your setup would look like somewhere else — the dry-run is non-destructive by design.&lt;/p&gt;

</description>
      <category>cli</category>
      <category>opensource</category>
      <category>showdev</category>
      <category>terminal</category>
    </item>
    <item>
      <title>umux: an open-source terminal workspace manager for Linux, Windows, and macOS</title>
      <dc:creator>Crystal Studio</dc:creator>
      <pubDate>Fri, 28 Aug 2026 10:51:03 +0000</pubDate>
      <link>https://dev.to/crystalstudio/umux-an-open-source-terminal-workspace-manager-for-linux-windows-and-macos-13nl</link>
      <guid>https://dev.to/crystalstudio/umux-an-open-source-terminal-workspace-manager-for-linux-windows-and-macos-13nl</guid>
      <description>&lt;h2&gt;
  
  
  TLDR
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;umux&lt;/strong&gt; is a free, open-source desktop app that organizes terminal windows into named &lt;strong&gt;workspaces&lt;/strong&gt; (one per project), each holding &lt;strong&gt;tabs&lt;/strong&gt; that split into any number of resizable &lt;strong&gt;panels&lt;/strong&gt;. It runs natively on Linux, Windows, and macOS from one codebase. It also watches the terminal data stream for the signals AI coding tools emit when a long task finishes, and fires a desktop notification — so you can step away while an agent works. Version 1.0.2, released 27 August 2026, is the first release with native Windows and macOS builds alongside Linux. It exists for developers who want the "many terminals, one place" workflow without learning tmux.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key facts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Platforms:&lt;/strong&gt; Linux (&lt;code&gt;.deb&lt;/code&gt;, &lt;code&gt;.AppImage&lt;/code&gt;, &lt;code&gt;.rpm&lt;/code&gt;), Windows 10+ (&lt;code&gt;.exe&lt;/code&gt; installer), macOS 11+ (universal &lt;code&gt;.dmg&lt;/code&gt; — Apple Silicon and Intel in one file)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Current release:&lt;/strong&gt; v1.0.2, 27 August 2026; nine tagged releases in total, from five dev previews to the 1.0 line&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Development timeline:&lt;/strong&gt; 53 commits between 27 June and 27 August 2026; 42 of them in August — the active build took under a month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tests:&lt;/strong&gt; 449 automated tests (115 Rust + 334 frontend), all passing at v1.0.2&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stack:&lt;/strong&gt; Tauri v2 — a Rust backend, a React + TypeScript frontend, terminals rendered with xterm.js&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Licence and cost:&lt;/strong&gt; MIT; builds are unsigned; infrastructure cost is $0 (GitHub Actions for builds, Cloudflare Pages for the landing page)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Telemetry:&lt;/strong&gt; exactly one anonymous app-open event, nothing else&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Layout model:&lt;/strong&gt; workspaces → tabs → unlimited split panels per tab, with minimum panel sizes and one-shortcut pane zoom&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key fact:&lt;/strong&gt; terminal output inside umux is byte-identical whether or not its inspector is running — the inspector reads the stream and never modifies it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is umux?
&lt;/h2&gt;

&lt;p&gt;umux is one window where all of a project's terminals live. A developer creates a &lt;strong&gt;workspace&lt;/strong&gt; named after the project — "shop-frontend", "server-migration" — and opens terminal &lt;strong&gt;tabs&lt;/strong&gt; inside it. Any tab's area splits into as many &lt;strong&gt;panels&lt;/strong&gt; as needed, resized by dragging dividers, with a minimum size enforced so nothing collapses to nothing. A keyboard shortcut zooms one panel to fill the tab and restores the exact previous layout afterwards; the covered panels keep running underneath.&lt;/p&gt;

&lt;p&gt;The whole arrangement survives a restart. Workspaces, tabs, panel layouts, and working directories are saved to a config file and restored when the app reopens. Each panel runs a real shell — the user's own shell on Linux and macOS, PowerShell on Windows — and renders a genuine terminal: colors, cursor movement, full-screen programs like &lt;code&gt;vim&lt;/code&gt; and &lt;code&gt;htop&lt;/code&gt; all work.&lt;/p&gt;

&lt;h2&gt;
  
  
  What problem does it solve?
&lt;/h2&gt;

&lt;p&gt;A working developer's terminal count grows with every project. Today's typical setup: a dev server in one window, an API in another, an SSH session into a remote machine somewhere, plus an AI coding agent churning through a task in a fourth. The windows pile up in the taskbar and the developer loses track — most acutely when an AI agent finishes a ten-minute task and nobody notices for twenty minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick answer:&lt;/strong&gt; umux replaces the window pile-up with one window per project, and it tells you when the AI agent is done instead of making you babysit it.&lt;/p&gt;

&lt;p&gt;The classic tool for this is tmux, and it is genuinely excellent — but it is a keyboard-first, text-mode world with its own prefix keys and configuration language. Plenty of good developers never learn it. umux delivers the same outcome (many terminals, one place, organized per project) through a graphical interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does umux work?
&lt;/h2&gt;

&lt;p&gt;umux is one app with two halves, built on Tauri v2.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Rust backend&lt;/strong&gt; owns everything that touches the operating system. It creates pseudoterminals (PTYs — the mechanism that makes a program believe it is talking to a real terminal), writes keystrokes into them, resizes them, and closes them cleanly. It also handles SSH connections, desktop notifications, and the config file.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;frontend&lt;/strong&gt; (React + TypeScript) renders the workspace UI and a real terminal surface per panel using xterm.js. Keystrokes flow from the terminal surface down to the backend; output flows from the PTY back up to the screen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key fact:&lt;/strong&gt; local panels and SSH panels are the same thing to the rest of the app — both are just a PTY behind one interface — so a remote machine's terminal behaves exactly like a local one.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does umux know when an AI agent finished a task?
&lt;/h2&gt;

&lt;p&gt;Terminals and the tools running inside them communicate through &lt;strong&gt;escape sequences&lt;/strong&gt; — special byte patterns embedded in the normal output stream. AI CLI tools such as Claude Code, Codex, and Aider emit standard OSC escape sequences (OSC 9;9, OSC 99, OSC 777) when a long task completes.&lt;/p&gt;

&lt;p&gt;umux feeds every byte of terminal output through a small parser that recognizes these sequences and turns them into events. An event becomes a native desktop notification, and it also drives a per-panel &lt;strong&gt;agent status&lt;/strong&gt; indicator: working while the agent streams, needs-attention when it waits for the user, idle once it exits.&lt;/p&gt;

&lt;p&gt;Three properties of this design matter:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;No polling.&lt;/strong&gt; umux never checks whether a process is still running on a timer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No screen scraping.&lt;/strong&gt; umux never reads the visible terminal content to guess what is happening.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No mutation.&lt;/strong&gt; The parser passes every byte through unchanged and only extracts events, so output stays byte-identical whether or not umux inspects it. Detection relies solely on the escape sequences — nothing else.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How does umux compare to tmux, cmux, and Herdr?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Quick answer:&lt;/strong&gt; pick tmux if you already live in a keyboard-driven terminal workflow; pick umux if you want that outcome in a GUI — with cross-platform builds the others don't all have.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;umux&lt;/th&gt;
&lt;th&gt;tmux&lt;/th&gt;
&lt;th&gt;cmux&lt;/th&gt;
&lt;th&gt;Herdr&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Type&lt;/td&gt;
&lt;td&gt;desktop app (GUI)&lt;/td&gt;
&lt;td&gt;text-mode multiplexer&lt;/td&gt;
&lt;td&gt;native macOS app&lt;/td&gt;
&lt;td&gt;CLI/TUI multiplexer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Platforms&lt;/td&gt;
&lt;td&gt;Linux, Windows, macOS&lt;/td&gt;
&lt;td&gt;Unix-like (Windows via WSL)&lt;/td&gt;
&lt;td&gt;macOS only&lt;/td&gt;
&lt;td&gt;terminal-based&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Interface&lt;/td&gt;
&lt;td&gt;point-and-click + shortcuts&lt;/td&gt;
&lt;td&gt;keyboard prefix, config file&lt;/td&gt;
&lt;td&gt;GUI sidebar&lt;/td&gt;
&lt;td&gt;keyboard prefix (Ctrl+B)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agent-finish notifications&lt;/td&gt;
&lt;td&gt;yes, from OSC signals&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;agent-aware&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Learning curve&lt;/td&gt;
&lt;td&gt;install and use&lt;/td&gt;
&lt;td&gt;prefix keys, copy mode, config language&lt;/td&gt;
&lt;td&gt;install&lt;/td&gt;
&lt;td&gt;prefix keys&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;cmux and Herdr both target the same new audience — developers running AI coding agents — and both are solid tools. The gap umux fills, per its creator: cmux carries more features than he needed and ships only for macOS; Herdr is a terminal-world tool with no desktop app. umux is the middle option — a simple desktop app, three platforms, one codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the known limitations?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agent status is the least polished feature.&lt;/strong&gt; By the creator's own admission it does not yet work perfectly. The completion notifications it is built on are the solid part.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Builds are unsigned.&lt;/strong&gt; umux ships without paid signing certificates (a deliberate $0-cost policy), so macOS Gatekeeper and Windows SmartScreen show a one-time first-run warning. The README documents the two-click workaround.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSH panels run on Linux and macOS today;&lt;/strong&gt; Windows SSH support is planned for v2.0.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linux is the reference platform&lt;/strong&gt; (Ubuntu on Wayland is what gets tested). X11 sessions are untested.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Steps: how to install umux
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Download&lt;/strong&gt; from &lt;a href="https://umux.pages.dev" rel="noopener noreferrer"&gt;umux.pages.dev&lt;/a&gt; or the &lt;a href="https://github.com/CrystalPlatforms/umux/releases" rel="noopener noreferrer"&gt;GitHub releases page&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pick the format:&lt;/strong&gt; Linux — &lt;code&gt;.deb&lt;/code&gt; (installs into the system) or &lt;code&gt;.AppImage&lt;/code&gt; (portable, no install); macOS — drag the &lt;code&gt;.dmg&lt;/code&gt; app to Applications; Windows — run the &lt;code&gt;.exe&lt;/code&gt; installer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;First run of an unsigned build:&lt;/strong&gt; on macOS, right-click the app and choose Open (once); on Windows, SmartScreen → More info → Run anyway (once). The README documents both.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create a workspace per project&lt;/strong&gt;, add a tab, split it into panels. The layout, working directories, and shells come back after a restart.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is umux free?
&lt;/h3&gt;

&lt;p&gt;Yes. It is MIT-licensed open source, the builds cost nothing to make (GitHub Actions), and nothing in the toolchain is paid for — including certificates, which is why builds are unsigned and the README documents the first-run steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which operating systems does umux support?
&lt;/h3&gt;

&lt;p&gt;Linux (Ubuntu/Wayland is the reference), Windows 10 and newer, and macOS 11 and newer. The macOS build is universal — one file covers Apple Silicon and Intel. Each platform gets its own native shell: PowerShell on Windows, the user's shell elsewhere.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do I need to learn keybindings or write a config file?
&lt;/h3&gt;

&lt;p&gt;No. umux is point-and-click first: workspaces are created and renamed in the UI, panels are split and resized by dragging, and a handful of shortcuts (such as pane zoom) speed up daily use. There is no configuration language to learn.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does umux detect that an AI coding agent finished?
&lt;/h3&gt;

&lt;p&gt;It reads the standard OSC escape sequences (OSC 9;9, OSC 99, OSC 777) that AI CLI tools emit on task completion, straight from the terminal byte stream. No process polling, no screen reading. The same signals drive a per-panel agent status indicator.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does umux change my terminal output?
&lt;/h3&gt;

&lt;p&gt;No. The inspector sits beside the stream, not in front of it: every byte passes through unchanged, and detection relies solely on the escape sequences. Output is byte-identical whether or not umux is running.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is umux a tmux replacement?
&lt;/h3&gt;

&lt;p&gt;Not for people already productive in tmux — it does not aim at them. It is an alternative for the larger group that never adopted tmux's keyboard-first world and wants the same organization through a GUI. There is no config file and no modal editing model to learn.&lt;/p&gt;

&lt;h3&gt;
  
  
  What data does umux collect?
&lt;/h3&gt;

&lt;p&gt;One anonymous app-open event, used to estimate active usage. Nothing else — no terminal content, no file names, no telemetry of any other kind. It can be turned off.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can umux connect to remote machines?
&lt;/h3&gt;

&lt;p&gt;Yes. An SSH panel opens a shell on a remote machine using the local SSH agent and keys, and behaves identically to a local panel. SSH on Windows is planned for v2.0.&lt;/p&gt;

&lt;h3&gt;
  
  
  How long did it take to build?
&lt;/h3&gt;

&lt;p&gt;Under a month of active work. The commit record spans 27 June to 27 August 2026 (53 commits), with 42 of them landing in August.&lt;/p&gt;

&lt;h2&gt;
  
  
  Last updated
&lt;/h2&gt;

&lt;p&gt;2026-08-28&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
