Aquí hi ha 64 versions de wmux, des de 15 d’abril del 2026 fins a l’actual, 4.10.0. Cadascuna enllaça amb els instal·ladors del mateix desenvolupador.
| Versió | Data | Mida | Fitxers |
|---|---|---|---|
| 4.10.0Darrera versió | 23 d’octubre del 2026 | — | 64 bits EXE Notes de la versió### Added
• **See when an agent is driving a browser tab, and stop it.** A browser tab
now shows a mark in its toolbar and on its tab while an agent is acting on
it. Stop ends the agent's current action and pauses it on that tab until
you resume; Take over hands the tab to you until you hand it back. Tabs of
your own Chrome that you lent to an agent can be returned from the
workspace's Chrome profile menu with Return to me. Before, the only sign
was the help bar, and there was no way to stop or take back a tab.
• **Office shows every workspace at once.** The Office plugin (by @bluemas) now seats every local workspace's agents in one office, so everyone who needs you queues at the same boss desk. Clicking an employee takes you to that workspace's pane. The office is scaled to fit the page, so it never scrolls. This needs a new plugin permission, `agent.state.read.all`, which the approval prompt lists on its own line; without it, Office shows only the current workspace, as before. An installed Office updates itself and asks for approval again (#2613).
• **Plugins shows what each catalog plugin looks like.** The detail for Office and Agent status now has a real screenshot of that plugin's page, between the credit line and the description. Before, you only saw a description until you installed and opened the plugin. A bundle you installed by hand shows no preview (#2618).
• **Run now can end a finished run's leftover session and start.** A finished
schedule run keeps its agent session open for up to 10 minutes, and until
now a Run now in that window was only refused with "Not started:previous
run's session still open", so you had to wait. Now the schedule offers to
end that session and start:an inline confirm names the session, Cancel is
focused, and confirming ends only that one session before the run starts. A
run that is still going never gets the offer, and scheduled runs are
unchanged. (#2625)
• **Bots in a group chat can react instead of replying, and a bot that stays quiet still shows it saw the message.** In a group chat, a bot woken by your message, or by another bot mentioning it, can answer with a single emoji. The emoji appears under that message as a small chip, the way a messenger shows a reaction. A bot that has nothing to add leaves a quiet acknowledgement there (👍, 👀, ✅ or 🙌, always the same one for that bot and message). Hover over a chip to see who reacted or who saw it. Before this, a bot with nothing to say left no trace, and a quick "agreed" took up a whole message. A reaction is only something you see:it never wakes a bot or starts any work.
• **A pane that hits its usage limit now offers what you can do next.** Click the limit chip in the pane's tab bar to open a small card. It also opens once by itself when the pane you are looking at hits the limit. From the card you can:
• Resume automatically when the limit reopens.
• Move the conversation to another account, when you have two or more. You can also tick "Always switch automatically".
• Continue in another agent that is installed and signed in. It opens in a new tab of the same pane, with a note about the work typed in for you to send.
• When every account is out, see the earliest time one reopens.
Before, the chip only offered a resume toggle and an account menu, and resuming was off unless you turned it on.
• **Keep the computer awake while agents work.** A new setting in Settings ›
General › Power stops the computer from going to sleep:Off, While working
(the default:only while an agent on this computer is working, as Fleet's
Running section counts it) or Always. The screen can still turn off.
• **Runs missed while asleep.** If the computer slept through scheduled runs,
the Schedules page says how many were missed and offers Run now, which
starts each of those schedules once, or Skip.
• **The Remote page checks Tailscale for you.** A short checklist shows
whether Tailscale is installed, signed in, has this PC on your network and
can see y |
| 4.9.0 | 22 d’octubre del 2026 | — | 64 bits EXE Notes de la versió### Added
• A bot's profile shows the commands it ran or was refused, a switch to turn its commands off, and an Always allow button that asks you to confirm before a bot may run a program; Settings › Bots can turn the command reviewer off (#2541)
• **New workspace setup.** Choose which git-ignored config files every new
worktree of a project gets, and its setup command, from the app:"New
workspace setup…" in the command palette, or Edit setup in the wmux.json
dialog. The `.env` family is ticked by default, the setup command is
suggested from the lockfile, and copying into bot and fan-out workspaces
stays off unless you turn it on. Saving writes `wmux.json` and approves
exactly what was written; a file with commands you have not approved yet is
sent to review first. (#2544)
• **A Preparing card for new worktrees.** A worktree you open (start from an
issue, Quick Launch, the Git page) is now prepared under a card at the top
of the sidebar that shows the copied files and how long the setup has run
against its 5-minute limit. If the setup fails, the card shows its last
output lines and offers Retry, Start anyway, or Discard. Discard removes the
worktree and the branch it made, and refuses if you changed anything in it.
Nothing starts and nothing is deleted without your answer. A failure, a
skipped setup or a missing file also shows a toast on any page. The first
worktree of a project with `.env` files and no copy settings offers to
choose files to copy. (#2545)
• **Add a whole bot team in one step.** The Bots page's "+" menu now has Add team, which asks only for the workspace and its repository. It adds the lead, research, developer, issues and reviewer bots the workspace doesn't have yet. Before, a workspace that already had a lead couldn't use Add team at all, and a default name that was already taken stopped the whole team. Roles that are already there are named instead of added, a taken name gets a number ("Developer 2"), and only a lead made here greets you. (#2551)
• **Archive for deleted bots.** A deleted bot's kept chat now goes under a folded Archive at the bottom of the Bots list instead of staying among your conversations. It still opens read-only, and Remove from Archive (asked in place) takes it off the list for good. Its messages stay saved, and what it wrote in group chats keeps its name. (#2551)
• **Bots can read from the services you signed in to.** A bot's research worker can now use a connection you signed in to in Plugins › Connectors (Notion, Google, Slack and the rest). Before this, a signed-in connection reached only your own terminals. The worker reaches the service through wmux, which keeps your sign-in to itself and lets the worker use only the tools you picked for that connection, and only when the service marks each of them read-only. Such a task carries no other connection and has no web search, no network for its commands and no repository, and it works with files only through its commands, which reach only its task folder. A bot starts, messages or resumes it only from a turn, in a conversation, that has taken in no outside text (your own message, for example); you can always resume it yourself. If the sign-in changes or wmux restarts, the bot tells you, and the worker starts again in a new pane once you resume it. macOS and Linux only for now (#2552)
• An HTML file a bot attaches now opens rendered in the Bots side panel, with Preview / Code to see its source, where before it showed only as code. An ```html block in a bot's message gets the same toggle (Code first). The page is drawn in a sandboxed frame:its scripts don't run, and it can't load anything from the network or reach the app (#2553)
• **Bot recipes.** Add bot now has a Recipe select with fifteen ready-made
jobs. Each one reads a service you connect (Notion, Figma, Canva, Linear,
Atlassian, Asana, GitHub, Gmail, Google Calendar, Sheets, Drive or Slack)
and reports in the chat. Anything to send or change comes to you as a
draft. A |
| 4.7.0 | 19 d’octubre del 2026 | — | 64 bits EXE Notes de la versió### Added
• **Bots write their own skills, and you approve each one.** After you
correct a bot, or after one of its tasks failed and then succeeded, the
bot can write down the procedure as a skill (a `SKILL.md` with a name,
description and version, kept in its own folder). Each proposal shows up
as an approval card with the whole change as a diff (a proposal too large
to show in full is refused); Approve loads it, Deny archives it, and
nothing loads before you approve. wmux keeps its own record of each
approved version and loads a skill only while its files are still that
version; one that changed since approval is marked in the profile and
stays unloaded until the bot proposes it again. An approved skill is
listed in the bot's wakes, where it reads it on demand, and is copied into
the worktree of every Claude Code worker it starts, kept out of git
(research workers get none). The bot's profile lists its skills and where
each stands, with Archive; archiving a skill posts a note in the bot's
chat, and the bot's next wake tells it not to apply that skill. An update
to a skill never changes the approved version until you approve it.
(#2288, #2300)
• **The phone gets what it needs to word bot cards in your language.** A
wmux system card in a room, such as a task done, a gate result or a hop
between bots, now carries its stable code and values to the phone for every
code the contract publishes. The phone can show the card in its own language
and still falls back to the English title. Before, the phone only had the
English text. (#2297)
• **The phone's Bots list shows the work each conversation handed off.** Each
1:1 and group chat lists the threads it started as the same work cards the
desktop draws:who the work was handed to, its state, the request and the
newest message. (#2297)
• **The phone knows what an approval is for.** An approval card names the act
its request asks for, so the phone can mark the ones that are approved on
the desktop only. (#2297)
• **Pause a bot from its profile.** A Pause button now sits beside Stop in a
bot's profile. It parks the bot at once, with no confirm, and the profile
then shows "Paused by you" with Resume. Before, the only way to park a bot
from the Bots page was Stop, which also ends its workers. (#2304)
• **Mute notifications for a single pane.** The pane menu (⋮ or right-click
on the pane header) now has Mute notifications. A muted pane stops popping
toasts, playing sounds, ringing, flashing the taskbar and sending OS
notifications. Its notifications are still recorded, and the sidebar still
shows its state. The mute is saved with the pane, so it survives a restart,
and a small bell-off icon in the pane header shows it is on. Before, you
could only mute a whole workspace or a whole notification category. (#2334)
• **Panes say when the daemon connection drops.** If the background daemon
goes away while wmux is running, every terminal pane that was attached to it
now shows a notice at once — reconnecting, then reconnected (which clears on
its own), or a lasting notice if wmux gives up, with what to do next. If you
typed or pasted into a pane while it was cut off, the pane says that input may
not have reached the shell, so you can check before typing it again. Before,
panes froze silently and that input disappeared without a trace.
• **Continue a Claude conversation on another account.** A pane running Claude
Code now offers "Continue on another account" in its pane menu. When the pane
hits a usage limit, its limit chip offers "Continue on…" with the same list.
Pick a registered Claude account and wmux stops Claude in that pane, copies
the conversation to the account and resumes the same conversation there, in
the same pane. The original transcript stays where it was. Before, an
account choice applied only to new terminals, so moving a conversation meant
quitting Claude and resuming it by hand. (#2336)
• **Account groups keep work and personal accounts apart.** In Settings ›
Accounts ea |
| 4.6.0 | 16 d’octubre del 2026 | — | 64 bits EXE Notes de la versió### Added
• **New group chat, and who a group message goes to.** The Bots page's "+"
now offers New group chat:a name and the bots of one workspace. A
group's name opens its settings to rename it, change its bots or delete
it (its messages stay saved). Above a group's message box, "To:everyone"
opens a checkbox per bot to send to some of them only; typing `@Name`
ticks that bot, and the choice resets after each message. After Add team,
one click makes a group chat with the new team. (#2224)
• **Change a bot's repository from its profile.** The Repository line has
Change, which uses the same folder picker as Add bot and checks the folder
the same way:the folder's origin must name an owner/repo, and a workspace
keeps one repository. Before, the repository a bot was created with could
not be changed. (#2227)
• **Window glass on macOS, with Off, Soft and Clear.** The window frame and
sidebar let the desktop show through in every theme, dark or light. Pick
how much in Settings › Appearance › Window glass; the terminal stays
opaque. (#2233)
• **Settings › Bots shows how much space bot task folders use, with a "Clean up now" button.** It applies the same rules to every bot task that has already ended, and says what it removed, what it kept because of uncommitted changes, and what is still in use. (#2234)
• **The phone can tell a bot's worker workspace from an ordinary one.** The desktop shows a factory bot's worker workspaces only on its Bots page, but the phone API still listed their panes as plain top-level workspaces, so the phone's Fleet counted rows the desktop hides. `GET /api/workspaces` rows and `GET /api/sessions` rows of such a workspace now carry an optional `botWorker:{ botId, taskId? }`. The rows are still listed, and nothing is removed or renamed. (#2250)
### Changed
• **A bot's private chat and the workspace room are separate.** What you say
to a bot in its chat, its answers, its greeting and the work it starts
there stay in that chat; the room shows only what is said in the room.
Before, the private chat was a view of the room, so the two mirrored each
other. Group chats are the ones you make (see below). Messages from the
phone to its bot land in that bot's chat too. (#2217)
• **The Bots item appears in the sidebar only after you turn bots on in
Settings.** Settings › Bots' switch now says that turning it on adds Bots to
the sidebar, and the item shows up right away. Turning the bots off while the
Bots page is open goes back to Workspaces, and the Bots shortcut and command
open Settings › Bots while they are off. (#2220)
• **Group chats are yours to make; a workspace no longer gets a room by
itself.** A group chat is a name and two or more bots of one workspace.
A message in it goes to every bot in it, or only to the bots you pick, and
a bot that has not spoken there yet introduces itself when it answers.
Before, a workspace with two or more bots showed a room on its own, and a
message to a room with a lead went to the lead alone. A room you had
written in becomes a group chat named after its workspace, with its
messages kept. (#2223)
• **Turning "Run bots" off now stops the bots' running work.** Before, off only paused:no new turn or worker started, but what was already running kept going. Now the switch is written first, so nothing new launches, and then the same stop as Stop all runs. Running turns end, open bot tasks are cancelled as "stopped by owner", running gates are cancelled, workers' processes are stopped, and routines are paused. While bots stay off, a worker launch that was already under way is stopped as soon as it registers. Nothing is deleted: worktrees, branches, scratch folders, logs and conversations stay. Turning bots on again reopens nothing. (#2226)
• **The agent bar is shorter:Files, Snippets, Rich Input, Schedule and
Multi Task.** Files now opens and closes the file tree column, and the
titlebar's file tree icon is gone. The file tree header has its own close
button. (#2229)
• **Se |
| 4.5.0 | 15 d’octubre del 2026 | — | 64 bits EXE Notes de la versió### Added
• **Releases now include a headless wmux for Linux hosts.** Each release
publishes `wmux-server-<version>-linux-x64.tar.gz` and `-linux-arm64.tar.gz`.
Each one bundles its own Node, so it runs on a Linux machine without root or
a system Node and puts the daemon and `wmux web` in `~/.wmux/runtime`. The
desktop app ships with the hashes of both files, so the upcoming "Add PC over
SSH" can verify what it installs. To install it by hand, see
`docs/how-to/install-wmux-server-manually.md`.
• **`wmux web pair`.** `wmux web pair --name <device> [--kind desktop|phone]
[--json]` starts a pairing on the web server that is already running and
prints its code, port and input grant. It never restarts the server, so
devices that are already paired stay paired, and it never prints the access
token. A computer paired with `--kind desktop` may also open new workspaces
on that host. Phones never can.
• **`wmux daemon status --json` reports more.** It now includes the daemon's
release version, how many panes are running, and whether the web server is
on (with its port and input grant).
• **Add a PC over SSH.** "Add PC over SSH…" in the computer switcher (and
from Connect a PC) lists the hosts in your `~/.ssh/config`, or takes
`user@host`, and does the rest:it installs the wmux server on that Linux
computer (checked against this app build), starts `wmux web` on loopback,
pairs this computer and adds it to the switcher, all over your own ssh with
your keys or agent. Before, a headless Linux box had to be set up and
paired by hand. wmux keeps one SSH connection open to the host while it is
paired and sends nothing until that connection is up and the host is the
one you confirmed. If the server there stopped while idle, wmux starts it
again, on the same port and settings, the next time it connects. When the
host's identity changes, "Check SSH connection…" shows
what changed and asks before trusting it again. Password prompts are never
answered for you:run `ssh <host>` once in a terminal first. (#2176)
• **Keep the daemon running on a Linux server.** `wmux daemon install-service`
sets up a systemd user service so the wmux daemon starts at boot and keeps
running after you log out of SSH. It never stops a daemon that is already
running, and it never runs sudo. If your account needs lingering, it prints
the one command to run. `wmux daemon uninstall-service` removes it and leaves
the running daemon alone. On macOS, or without systemd, it prints the command
to run under your own supervisor instead.
• Add PC over SSH:an opt-in **Start after reboot** checkbox installs the wmux daemon on that computer as a login service (Linux with systemd), and the PC switcher's host settings get a matching on/off. The dialog says plainly when the host cannot run it, or when linger is off and shows the one `sudo` command to run there.
• **New workspaces on a computer added over SSH.** With that computer selected
in the PC switcher, the sidebar's `+` (and the collapsed rail's) now opens a
new workspace on that computer, with a shell running there, and shows it in
its list. It appears only for computers that let this desktop create
workspaces; other paired computers still have no `+`.
• **Your lead bot can run a relay.** When the coordinator hands work to a bot, it can name the bots that follow — say research, then build, then triage — and wmux passes each result straight on. The coordinator hears back once, with the final result or why the relay stopped. The work runs in its own thread, and General gets one "Finished" or "Stopped" card under your message that opens it. (#2193)
• **Add a whole team at once.** "Add team" on the Bots page adds a lead and four role bots — research, build, triage and review — to the current workspace. Only the lead greets you; in that room the composer shows you're talking to the lead, and the others join when it hands them work or you @mention them. If you haven't pinned a bot for the phone, the new lead becomes the one your p |
| 4.4.0 | 14 d’octubre del 2026 | — | 64 bits EXE Notes de la versió### Added
• **A log line when a remote pane cell stays blank.** If a mirror cell in a
remote workspace is still not attached 5 seconds after it asked, with no
error shown, wmux now writes the cell's recent attach steps to the log
(`[wmux:remote-attach]`):when each run started, whether it was still
waiting for the previous run to close, whether the attach was sent, and
when (or whether) it was answered. It changes nothing the cell does; it is
there so the next blank cell says why (#2101). (#2156)
• **Hand a page element to the agent from the browser.** The browser
inspector used to copy an element's selector and ask you to paste it into
the agent yourself. Now picking an element opens a bar with a note field;
Send types your note and the element into the input line of the agent
running in the same pane and focuses it, and nothing runs until you press
Enter. A pane with no agent running gets Copy instead. (#2158)
• **Experimental Rust terminal engine.** Builds that include the native module can select Rust in Settings → Terminal → Performance for ordinary and team sessions. Node remains the default; changing the engine requires restarting the app and daemon as applicable. (#2163)
• **Bots.** A new Bots page, right under Workspaces, where you keep agents on
a team and talk to them like a messenger. Each workspace is a group room
and each bot has its own chat. Create a bot with just a name and a job, or
start from a template. A message in a room reaches every bot there, or only
the ones you mention, and bots answer each other within fixed limits. A bot
can schedule its own check-ins, start workers in their own worktrees, and
ask you for an approval, a key or a login in a separate window. Merges
happen only after you approve them, and the app performs them itself. You
can approve by typing "merge it", with a 10 second Undo. Finished workers
are stopped and their panes closed. A paired phone whose input permission
you turned on can approve a bot's request too. Bots are off until you turn
them on in Settings › Bots. (#2164)
• **Images and PDFs open in a preview tab that follows the file.** Clicking
an image or a PDF in the file tree now opens a read-only preview beside the
terminal, instead of the text editor, which showed an image as garbage and
anything over 1 MB as nothing. When an agent rewrites the file, the view
updates in place and keeps its zoom and the page you were on; a
half-written or deleted file leaves the last good version up until a
complete one arrives. Zoom with Cmd/Ctrl + scroll or the toolbar, and open
the file in its default app, open its folder or copy its path from the tab.
(#2150)
• **HTML files open rendered, offline and sandboxed.** Clicking an `.html`
file in the file tree now shows the page in the preview tab beside the
terminal, for coverage reports, charts and built docs an agent produces.
It reloads in place when a file it uses changes. The page runs in its own
sandbox and is offline until you press **Network on** for that tab;
nothing it links to opens without a click, and **View source** still
opens the file as text. (#2150)
### Changed
• **Browser, editor and diff tabs open beside the terminal.** A pane is now a
terminal column plus a work area:browser, editor and diff tabs draw on the
right under their own tab strip, on the same header line as the terminal
tabs and split where the pane is. Before, a browser sat beside the terminal
but an editor or diff tab covered the whole pane. The expand toggle moves
from the browser toolbar to that strip and works for any of these tabs;
picking a terminal tab brings the split back. (#2155)
• Internal:saving the Token usage surfaces store (`surfaces.json`) and editing JSON config keys are split into short steps (read what is on disk, replay this window's changes, write; one edit at a time, then format like the original file). Cognitive complexity 125 and 47 down to 3 and 4. Golden-file tests pin the full outcome first; what is written is unchanged. (#215 |
| 4.3.1 | 13 d’octubre del 2026 | — | 64 bits EXE Notes de la versió### Added
• **Commits, pushes and PRs refuse passwords and keys.** Commit, Push and
Create PR on the Git page, adopting a task into its parent, and Moa's
delivery now stop a change that adds a `.env` / `.env.local` file, a private
key or keystore, a credential store, or a key-shaped value (OpenAI,
Anthropic, GitHub, GitLab, AWS, Stripe, Slack, npm and Twilio keys, private
key blocks, a long random value assigned to a key/secret/token/password).
Every commit a push or PR sends is read on its own, and the message names
the file and line without repeating the value. Templates (`.env.example`),
public certificates, Keynote files, debug keystores and `.env.production`
files without secrets go through as before; a file already in the
repository is judged by what is added to it. The check is on by default and
can be turned off in Settings › General. (#2107)
• **Commits from any terminal, editor or agent are checked for passwords and
keys.** wmux installs a `pre-commit` hook in the repository shown on the Git
page and in the repository behind every Moa / fan-out task worktree, so a
commit made outside wmux's own buttons is stopped by the same rules, with a
plain message that names the file and line but never the value. A
`pre-commit` hook you already had is kept and still runs after the check;
repositories that set `core.hooksPath` (husky, lefthook) are left alone. On
by default; turning it off in Settings › General › Git removes the hook and
puts yours back. (#2110)
• **The weekly retro shows how often you had to step in per finished task.**
Each task Moa tracks now counts the times you acted on it:decisions you
answered, approvals you pressed, and posts you made in its mission channel.
Answers and presses from agents, Moa's approval lane and the brain are not
counted. The retro details then show the median for the tasks finished that
week. Before, the retro only had weekly totals of decisions and approvals,
with no link to the tasks they were about. (#2126)
• **Sidebar port numbers can be hidden.** A "Show port numbers" switch under
Appearance > Sidebar, on by default; the choice survives a restart. (#2132)
• **Hide the sidebar row's folder and copy buttons.** Settings › Appearance
has two new switches, on by default, that remove "Open in File Explorer" and
"Copy session info" from a workspace row's hover buttons. The row's
right-click "Open with" menu still opens the folder. (#2135)
• **A pane no longer stays "running" after you interrupt Claude Code.** Claude
Code fires no `Stop` hook when you press Esc mid-turn, so a hook-tracked pane
stayed `running` until your next prompt. The new optional `wmux-turn-signals`
mod (Claude Code 2.1.296+, installed with
`/plugin install wmux-turn-signals@wmux`) reports the interrupt through the
existing hook bridge, and the pane settles within about a second. wmux treats
it as a turn you stopped yourself, so no "work finished" alarm plays. When a
queued prompt starts the next turn right after the interrupt, the mod sends
nothing and that turn keeps the pane. (#2137)
• **Open a link in a new browser tab.** Ctrl/Cmd+Shift-click a link in the
terminal, or run `wmux open --new <url>`, to open it in a new tab of the
browser pane instead of replacing the page you are on. `wmux open --new`
opens the tab in the background, so you keep typing in the terminal.
(#2147)
• **The browser can fill a split pane without closing the terminal.** When a
pane holds a terminal and a browser, they sit side by side and neither side
could go below 20%, so giving the browser the whole pane meant closing the
terminal. The browser toolbar now has an expand toggle:the terminal side
hides (its program keeps running at the same size) and the browser fills
the pane. Show terminal, or picking the terminal's tab, brings the split
back at the same widths. (#2151)
### Changed
• Internal:the Token usage inventory readers for Claude Code, Codex and Antigravity are split into one function per kind of item and share one collec |
| 4.3.0 | 11 d’octubre del 2026 | — | 64 bits EXE Notes de la versió### Added
• **Point an agent at a pane by its name:`#w1-2` or `#backend`.** Every pane already shows a unique name in its header (`w1-2`, plus the agent running in it) or the name you gave it. Type that name with a `#` to an agent and it can pass it straight to the wmux tools — `terminal_send`, `terminal_read`, the `pane_*` tools and `send_message` (as `to`, `pane_id` or `surface_id`) all accept it where they used to need a long pane, surface or terminal id. Before, targeting a pane meant pasting a block of ids from the pane header. `pane_list`, `a2a_discover` and `a2a_whoami` now report each pane's `paneName` and `paneTag`, and a name only reaches what its ids could, with the same checks. (#1954)
• **Dragging a pane header into a wmux terminal types just its tag.** Drop the pane header on a terminal and it inserts `#w1-2 ` instead of the full block of ids, ready for the prompt you are writing to an agent. Dropping it on another app still gives the full description, which now also lists the pane tag (and the pane's name when you named it). (#1954)
• **Dismiss a question that needs no answer.** When an agent ends its turn on a question you don't need to answer, right-click its workspace in the sidebar or open the row's menu in Fleet and choose **Dismiss question**:it stops counting as Needs you, and stays dismissed after a restart. Approval and permission prompts still wait for you. (#1957)
• **Connect a PC… on the Remote page.** One dialog covers both ends. On "Invite this PC" it turns cross-PC A2A on if needed, then creates and copies the invite, marking the tailnet address. As soon as the other PC joins, it asks what that PC may see. On "Paste an invite" it accepts an A2A invite, a pairing link, a `wmux web` address with its token, or an address and a code. Opening the dialog changes nothing, and the clipboard is read only when you press Paste. Before this you had to pair PCs from Settings › LAN.
• **Kitty keyboard protocol in terminal panes (macOS and Linux).** wmux now answers the kitty keyboard query, so Claude Code switches to the protocol inside wmux. Codex's request for the protocol now takes effect too. Once an app has asked for it, Shift+Enter, Escape and Ctrl+letters reach the app exactly as it expects instead of through wmux's workarounds. Before, an app either never asked or got a mix of encodings. Korean and other IME input is unaffected:the key that picks an IME candidate no longer leaks into the app next to the committed text, a known xterm.js issue that wmux works around here. An app that exits without switching the protocol back off no longer leaves the shell receiving encoded keys. Windows keeps the previous behaviour for now. (#1963)
• **Pane names now work in channel mentions and Moa hand-offs too.** A channel post's mention can pin a pane with `#w1-2` or `#backend` instead of its pane id, and Moa can hand work to `#backend` instead of looking up the terminal id first. These were the last two places that still needed the raw id after pane names became addresses.
• Connect a PC's invite can also let the other PC see this PC's workspaces. Tick the new box, and the copy holds the invite plus a view-only pairing link on a second line. The box is off by default and offered only while Share & pair is on over HTTPS. The other PC pastes once and both connect.
• **Groundwork for pushing, opening PRs and merging from the phone.** `wmux web`
gains `--allow-git-write` (off by default) and `--git-write-login <login>`, the
host-side switch and GitHub account for upcoming phone push, PR creation and
squash merge. The gate needs an input grant that was set explicitly for the
device, push and merge need a fresh preview and a single-use confirmation,
and every request leaves a receipt kept for 72 hours so a resent request never
runs twice. No action is served yet, and the phone is not offered any of them
until it is.
• **Scheduled runs can use Claude's auto mode, and new schedules run unattended by default.** A new |
| 4.2.0 | 8 d’octubre del 2026 | — | 64 bits EXE Notes de la versió### Added
• **Agents can open apps.** The computer tool's new `openApp` action launches an app (by name, bundle id or path) or brings it forward, so an agent no longer depends on the app already running.
• **An agent cursor and a halo.** While an agent drives an app, a second cursor shows where it acts and a halo outlines the window it works in. Turn it off in Settings › Computer use › Show agent cursor and halo.
• **Permission buttons on macOS.** Settings › Computer use shows whether Accessibility and Screen Recording are allowed, with Request access, Reset access (for an entry that reads as on but no longer works) and Show helper in Finder. When a permission is missing, the message now names where the helper app is.
• **A Chrome profile can belong to one pane, so two panes in one workspace can be signed into two different accounts.** On the Chrome browser backend, the pane menu (⋮ or right-click on the pane header) now has **Browser profile** — pick a profile, create a new one named after the pane, or go back to the workspace profile — and **Show in Chrome**, which brings that pane's Chrome window to the front. Before, a profile could only be bound to a whole workspace, so every pane in it shared one Chrome and one set of logins. Each pane's agent now drives its own Chrome; its logins survive agent and app restarts, and a restarted agent keeps using its pane's tab instead of opening a new one. A profile bound to a pane is exclusive to it:the default and live profiles, a workspace's profile and another pane's profile cannot be bound, and one pane cannot close or take over another pane's tabs. In a workspace that has pane-bound profiles, an agent whose pane cannot be identified is refused instead of falling back to the workspace profile, which would act as a different signed-in account. Downgrading to an earlier version drops pane bindings (profiles and their logins are kept). (#1945)
• **Cross-PC A2A also works over Tailscale.** Two of your own PCs on one tailnet can now pair and stay connected when they are not on the same LAN, for example a desktop at the office and a laptop at home. An invite lists the PC's LAN addresses first and then its tailnet address, marked "(Tailscale)" in Settings › LAN › Cross-PC A2A. Before, an invite from a PC with a LAN address never included its tailnet address, and an address that did not answer while pairing was forgotten, so a laptop moving between the office and home lost the connection. The joining PC now keeps every address from the invite. When a connection gets through at an address that is not first in the list, that address is tried first from then on, so after a move only the first reconnect waits for the address that no longer answers. The certificate pin and the rule that only people create links are unchanged, and networks without Tailscale behave as before. (#1949)
### Changed
• **The phone knows when Moa's agent mode blocks a wake.** When Moa is on but
its HQ workspace's agent mode is off, the daemon no longer offers the phone a
wake that could only fail:`/api/config` now says `moaWakeBlocked:
"moa-mode-off"` instead of `moaWake:true`, so the phone can tell you to turn
the mode on rather than send a message that comes back refused. (#1928)
• **The Polish Settings page for keyboard shortcuts is called "Skróty
Klawiatury".** It used to say "Klawiatura", which read like settings for the
keyboard itself rather than the page that sets shortcuts. (#1937)
• **Copilot CLI hooks are marked as verified on a live CLI** (Copilot 1.0.93).
`wmux setup-hooks --agent copilot --status` no longer says wmux has not seen
Copilot load them. (#1938)
• **Computer use no longer asks before each app.** Once you turn computer use on, an agent can drive any app that is not blocked without a consent prompt per app. Before, every new app raised a prompt, so doing the task by hand was often faster. The prompt is still there as an option:Settings › Computer use › Ask before each app.
• **A shorter |
| 3.66.0 | 2 d’octubre del 2026 | — | 64 bits EXE Notes de la versió### Added
• **The phone can read your channels.** A paired phone can now list the
channels you can see, page through their messages and mark them read. A
phone allowed to type can also take your seat in a channel. The phone and
the desktop share that seat, so a channel you read on one surface is read on
the other. A message that mentions you arrives on the phone's event stream as
`channel.mention`, and a busy channel cannot crowd pending approvals out of
that stream. The daemon advertises `channels:true` in `/api/config` so the
app knows the feature is there. You still cannot post from the phone.
• **Computer use on macOS.** wmux now includes "wmux Computer Use", a small
helper app that lets agents you approve read and operate other Mac apps
through their accessibility tree, window screenshots, the mouse and the
keyboard. Computer use is still off by default. On a Mac it needs macOS 14
or later, Apple silicon, and two permissions you give in System Settings ›
Privacy & Security:Accessibility, and Screen & System Audio Recording for
screenshots. The permissions go to "wmux Computer Use" itself, not to wmux,
so the shells and agents running in wmux do not get them. The helper runs
only when wmux itself starts it. It never types into password fields, and it
types text directly instead of going through your clipboard.
### Fixed
• **Computer use says plainly that this build has no helper.** 3.65.0 let you turn computer use on before any native helper shipped; agents then got a raw spawn error with a file path and tried to work around it. Now they are told the helper is not in this build yet and not to try other ways to control the desktop, wmux does not claim the stop key, and Settings cannot turn the switch on (it can still turn it off). (#1698)
• **The macOS stop key no longer force-quits apps.** It is now Control+Option+Shift+Esc on macOS:Cmd+Option+Shift+Esc held down force-quits the frontmost app, so a panicked press would have killed the document an agent was editing. Windows and Linux keep Ctrl+Alt+Shift+Esc. (#1698)
• **Phone chat no longer gets stuck after Stop right after a send.** If you
stopped a Claude Code turn from the phone before it printed anything, Claude
put your message back into its input box. Every later phone message was then
refused until someone cleared that box in Terminal. Now the daemon clears it,
but only after a Stop that interrupted the turn, when the box holds exactly
the message the daemon sent to start that turn, and nobody has typed in the
pane since. It uses Ctrl-U, which you can undo in Terminal with Ctrl-Y. A
queued phone message waits for this instead of failing. The cancel receipt
reports it as `promptRestored`, `inputCleared` and `restoredMessageId`.
• **Keys are released right away when computer use is stopped.** A modifier
or mouse button held by an input action that timed out, crashed or was
stopped with the stop key is now released at once. Before, it stayed held
until the agent's next request.
• **Quitting wmux ends computer use for good.** A request that arrives while
wmux is quitting no longer starts a new helper or takes the stop key again.
### Security
• **Computer use refuses system-wide shortcuts and more system apps.** Agents
can no longer send shortcuts that act on the whole system instead of the app
they were given:Windows-key chords, Alt+Tab, Ctrl+Esc and Ctrl+Shift+Esc on
Windows, and Cmd+Tab, Cmd+Space, Force Quit, lock screen and log out on
macOS. These are refused before any consent prompt. System Settings, Task
Manager, Registry Editor, Script Editor, Automator, Shortcuts, Activity
Monitor and more shells and terminals are now on the blocklist.
• **Window titles wait for consent.** Listing windows no longer sends an app's
window titles to the agent's model provider until you have allowed that
agent to use the app. Until then, only the window ids and positions are
sent.
## What's Changed
• fix(computer):say plainly that this build has no helper, and hold nothi |
| 3.65.0 | 1 d’octubre del 2026 | — | 64 bits EXE Notes de la versió### Added
• **Orchestrator effort picker.** Settings → Orchestrator has an effort row
(low / medium / high / xhigh / max, or the CLI default). It reaches both
Claude brains — the SDK brain as `options.effort`, the terminal brain as
`--effort` — and, like the model, applies from the next turn:an idle brain
is swapped, a busy one finishes its turn first. (#1677)
• **Model discovery for agent CLIs.** Main can now ask an agent CLI which
models it runs — `agy models` for the Antigravity CLI, `codex debug models`
for Codex (with each model's supported reasoning levels), and a built-in list
for Claude — through `electronAPI.agentModels.list(agent, refresh)`. Results
are cached for 24 hours in `model-catalog.json` in the wmux data folder;
discovery runs only when asked, never at startup, and a missing CLI or
unreadable output yields an empty `unavailable` result instead of an error. (#1677)
• **Roles & fan-out:models to pick, effort and permission options.** Each
role row's model field now opens the models its agent CLI reports (`agy
models`, `codex debug models`, Claude's list), filters as you type, still
takes any id by hand, and has a Refresh models button. Under the row:an
effort selector (Claude `--effort`, Codex `-c model_reasoning_effort=…`,
and for agy the effort variant of the chosen model, since agy encodes it in
the model id), a Skip permissions checkbox that uses each CLI's own flag
(`--dangerously-skip-permissions`, `--dangerously-bypass-approvals-and-sandbox`),
and a mono preview of the launch the binding produces. A flag already typed
on a launch, or in the role's extra args, still wins, and turning Skip
permissions off on the resume chip or the recovery pill wins over the
role's Skip permissions for that launch. The model list is keyboard-operable
(arrow keys, Enter, Escape). (#1677)
• **`wmux role resolve <Role> [--json]`.** Prints what a role is bound to in
Settings → Roles & fan-out — agent, model, effort and exec-ready `argv` /
`flags` in each CLI's own grammar — so a project's own dispatch scripts can
follow the same bindings as the panes wmux launches. It reads the app's
`session.json` directly (works with wmux closed), normalizes it the way the
app does, and exits 2 when the role is not bound. (#1677)
• **Desktop computer use, opt-in (groundwork).** Agents running in wmux can be
allowed to see and control other desktop apps through one `computer` MCP tool.
Turn it on in the new Settings › Computer use tab. It is off by default, and
the tool does not exist for anyone who leaves it off. wmux asks you once per
agent and app. Password managers, terminals and other agent apps, wmux
itself, and system sign-in or administrator prompts are always refused.
`Ctrl/Cmd+Alt+Shift+Esc` stops every agent at once; wmux holds that
shortcut only while computer use is on, and if another app already owns it,
agents can look but not act until it is free. This release carries
the tool, the consent prompts and the settings. The small helper program
that reads and drives apps on Windows and macOS ships separately; until it
does, the tab shows "Not in this build yet". (#1683)
• **A role can start each new task in a fresh conversation.** Settings →
Roles now offers "Fresh context per task" for roles bound to Claude Code or
Codex. When the orchestrator hands such a pane a NEW task
(`terminal_send` with the new `new_task` flag), or another agent sends it a
new task with `send_message`, wmux first types the agent's own
fresh-context command (`/clear` for Claude Code, `/new` for Codex), waits
until the pane shows it finished, and only then delivers the task. Before,
a long-lived worker pane carried every earlier task's conversation into the
next one. Both keys are needed:the role's setting and the caller's
new-task signal, so a follow-up, a reply or a status update never clears a
pane, and no agent can clear a pane whose role did not opt in. A pane whose
agent is working, whose input box holds a draft, which runs a different
agent than |
| 3.63.0 | 29 de setembre del 2026 | — | 64 bits EXE Notes de la versió### Added
• Remote popover:**Conversation access** (phone Chat view), **Photo & file upload**, and **Dangerous launch** under a closed-by-default **Advanced** section with a warning. While the server runs, these toggles and **Allow input** apply immediately without a restart. The port, pairing token and paired devices stay the same.
• `wmux web --no-allow-input`, `--no-allow-upload`, `--no-allow-transcript`, `--no-allow-dangerous-launch`, `--loopback` and `--no-tls` turn one setting off on a re-run.
• **Decline a terminal dialog from the phone.** `POST /api/approvals/:id/decline`
(capability `terminal-prompt-decline`) sends one Esc, but only when the
daemon can prove the dialog on screen is the one the card was made for. If
it cannot, or the dialog is already gone, the phone gets 409/410 and
nothing is typed.
• **The sidebar says which pane asked for each fan-out task.** A task row now carries a muted line of its own under its name:`by <pane>` with the pane's coordinate first (click to jump to that pane), the pane's name marked `· closed` once it is gone, `Started by you`, `by Orchestrator`, or `Requester unknown`. Before, a workspace with two agent panes grouped all their tasks under one owner and the calling pane was only in a hover tooltip that could lose track of it after a daemon recovery. The requester is now recorded on the task's lineage stamp by stable pane ids, so it survives PTY rebinds and the pane being closed. Each agent row in a workspace's roster shows `N requested` for its own open tasks, and Fleet names the requester on a task's row in every section. (#1575)
• **Connect another computer from the Remote popover.** The sidebar Remote
popover's "Share this computer" section now has two cards:"Connect a
phone" (the QR and code, unchanged) and "Connect another computer", which
names the device, asks whether it may type, and shows one pairing link with
Copy and a live expiry countdown. The link only works in the wmux app:
opened in a browser it pairs nothing and says where to paste it. It is
offered only over HTTPS that another machine can reach; otherwise the card
says what to turn on. Before, pairing a second computer meant reading an
address and a code across two fields. (#1579)
• **Paired-device status at a glance.** The Remote popover reads "N paired ·
M active now" with phone and computer glyphs, and Paired devices shows each
device's kind and an Active now dot. Before, the roster showed only names
and a last-seen time. (#1579)
• **Other computers in the Remote popover.** The sidebar Remote popover now
lists every computer this one has paired with, each with a status:Connected,
Reachable, Unreachable or Needs re-pairing. The list appears at once and the
statuses fill in as each computer answers, so one that is off never holds the
others up, and an unreachable computer is never sent back to pairing. Click
one to see and attach its workspaces. (#1580)
• **Pair a computer by pasting one link.** "+" in Other computers takes the
pairing link from the other computer's Remote popover (or a phone pairing
link, an address and a code, or a `wmux web` link) in a single field, with a
Paste link button. A computer that needs re-pairing is paired again in place,
keeping its attached workspaces. Before, pairing meant copying an address and
a code into two fields of a separate dialog. (#1580)
• **The phone API can draw fan-out tasks under the pane that asked for them.** `GET /api/sessions` rows and `GET /api/workspaces` pane entries now carry the desktop `paneId`, so a phone can group tabs into panes. A nested fan-out task row carries `nestedUnder` (`pane` or `closedPane`), plus `requesterPaneId` for `pane`. This matches the desktop sidebar's workspace › requesting pane › tasks tree. Before, the phone could only nest tasks under the workspace. Clients that ignore the new fields keep drawing the workspace-level nesting from `nested`. (#1583)
• **`/turns` says why an OpenCode pane is unavailable.** An unavailable bod |
| 3.62.1 | 27 de setembre del 2026 | — | 64 bits EXE Notes de la versió### Fixed
• **⌘⇧2 no longer does nothing outside an agent pane on macOS.** Pressing the
mention-an-agent shortcut in a plain shell pane, or with the sidebar focused
while a shell is active, used to be silently ignored — no picker, no hint.
It now shows "Focus an agent pane to mention another agent". F2 on Windows
and Linux, and any Mac binding without ⌘, still pass through to the shell
(mc, htop, vim) as before. (#1559)
### Security
• **Agent-to-agent and channel deliveries respect pending approvals.** A2A messages, company messages, channel mention deliveries and channel wake nudges no longer submit into a pane that is showing an approval the workspace policy does not let an agent answer. They now go through the same input check as `terminal_send`, re-checked right before the Enter. A held delivery is not lost:it stays queryable and tells the sender why (`approval_pending` or `gate_unavailable`). A terminal approval also stays tracked while its dialog is still on screen. (#1560, GHSA-hvqg-29w6-q3g8, GHSA-xxqv-cx7h-8vgf)
## What's Changed
• test(approvals):make the terminal-prompt key-refresh tests deterministic by @openwong2kim in https://github.com/openwong2kim/wmux/pull/1558
• fix(mention):explain a declined ⌘⇧2 on macOS instead of doing nothing by @openwong2kim in https://github.com/openwong2kim/wmux/pull/1559
• fix(delivery):route non-operator pane deliveries through one gated submit by @openwong2kim in https://github.com/openwong2kim/wmux/pull/1560
• chore(release):3.62.1 by @openwong2kim in https://github.com/openwong2kim/wmux/pull/1561
**Full Changelog**:https://github.com/openwong2kim/wmux/compare/v3.62.0...v3.62.1 |
| 3.61.0 | 25 de setembre del 2026 | — | 64 bits EXE Notes de la versió### Added
• **Every built-in shortcut can be moved or switched off.** Settings →
Shortcuts now lists all of wmux's keyboard shortcuts — workspace switching,
tab and pane cycling, focus movement, zoom, panels — each with its current
key. Click the key to record a new one, untick the row to hand the key to
the terminal, or reset it. Alt+Up / Alt+Down (previous / next workspace)
were the trigger:TUI apps such as Codex and Crush bind them, and wmux took
them with no way to give them back. A new key is refused when it would
take a key another shortcut uses, copy / paste, the prefix key, or a key
with no Ctrl / ⌘ / Alt. Sessions that switched shortcuts off under the old
toggle keep those settings (#1456).
• **A fan-out owner can read and nudge its workers' panes.** The agent or
orchestrator that started a fan-out can now read the terminal of each open
task it delegated, send it plain text, and stop it with Ctrl+C or Escape,
without anyone switching workspaces. Before, those panes were out of reach
because they live in other workspaces. Access ends when the task is
finished. Text read from a worker comes back marked as untrusted, since the
worker printed it. Text sent to a worker's pane may contain only letters,
tabs and newlines:control characters and raw writes are refused, so text
can't do what the key tool withholds. Note the limit:a pane agent's
identity is the pane id its MCP server reports. wmux checks which workspace
owns that pane, but it can't prove the caller is that pane, so another
program running as you could claim to be the owner.
• **Worker permission mode for fan-out.** Settings → Agents → Fan-out workers
picks the Claude Code permission mode workers launch with (Auto by default;
Accept edits, Bypass permissions or Manual). In every mode a worker may
record its task ledger row and read its mission channel without a prompt,
and is denied the wmux tools that reach beyond its own task:fan-out, typing
into other panes, messaging other agents and the browser.
• **"Allow wmux worker tools in Claude Code" button.** Adds the same minimal
allow list to `permissions.allow` in `~/.claude/settings.json`, keeping
everything else in the file. That file applies to every Claude Code session
on the machine, and the button says so.
• **Recent unattended fan-outs in Fleet → Approvals.** Shows what ran without a
prompt, when, from which workspace and in which repository.
• **The sidebar shows who each agent is.** Every agent row leads with a small
drawn monogram for its kind (C Claude Code, X Codex, G Gemini, A Aider,
O OpenCode, P Copilot, OC OpenClaude, K Kiro, R Grok; a terminal mark for a
shell), and a collapsed workspace shows up to three of them grouped by
status instead of a bare agent count. Agent rows also show live activity
and how long ago the agent last did something.
• **Fan-out tasks nest under the workspace that launched them.** Task
workspaces sit indented under their owner with a fold chevron and a
`N tasks · M need you` line, and a menu on that line closes every finished
task at once — worktree and workspace — while keeping any task with
uncommitted or unpushed work and saying why. A task counts as finished only
when every agent in it has finished. Tasks whose owner was closed
collect under "From closed workspace"; detached tasks stay on their own.
The `wtask:` prefix no longer shows.
• **Where a task came from.** A task row's fan-out mark says which workspace
fanned it out, who asked (you from the Multi Task dialog, the
orchestrator, or the pane that called it) and when, and a task workspace's
titlebar has a link back to its owner.
• **Recent activity order.** Settings › Appearance › Sidebar › Workspace
order now offers Recent activity next to Manual and Needs you first.
• **Resizable sidebar.** Drag the sidebar's inner edge (220–400px, default
264px); double-click to reset. Terminals resize once, when you let go.
• **"Changed since you last looked" dot.** A small dot on a workspace row
and its agent row sa |
| 3.60.0 | 23 de setembre del 2026 | — | 64 bits EXE Notes de la versió### Added
• **See what changed while Fleet was closed.** A needs-you row whose status changed since you last closed Fleet is marked with a small dot. (#1446)
• **Act on a pane without leaving Fleet.** Each row has Jump, Message, Stash, Label and Close verbs behind a ⋮ menu, with m / s / l / Backspace shortcuts on a focused row. Close asks first, with Cancel as the default. Remote rows offer Jump only, and a running agent cannot be messaged mid-turn. (#1446)
• **Agents can ask "who needs me?" with `fleet_triage`.** A new MCP tool (full, core and commander profiles) returns the Fleet board as data:Needs you, Running and Idle rows with each agent's status, one line of detail and how long it has been quiet, plus the tab to act on. It is computed by the same selector the Fleet overlay renders, so an agent sees exactly what you see, across every workspace unless one is named. Before, an orchestrator had to poll `pane_list` per workspace or read terminals to find a blocked agent. Third-party plugins need the `terminal.read` grant, since rows carry agent-authored text. (#1449)
### Changed
• **Every finished turn now reports its closing message, not just a closing question.** Main used to forward the agent's last message to the renderer only when it ended on a question. Each turn end now also sends the message tail per pane, cut to the same 140-character budget the phone list uses, so Fleet rows can show what an idle pane last said. Claude Code only for now; other agents, failed turns and new sessions clear it. (#1446)
• **Fleet is an attention board, not a card grid.** Agents are listed in three sections — Needs you, Running and Idle — instead of a grid of identical cards. Each row shows one line of detail (the pending question, the agent's last message or its current tool activity) and how long it has been since the pane last did anything. Idle agents collapse into a single "Idle N · oldest 2d" row, and when nothing needs you Fleet says so. Status filters and search narrow the sections; raw terminal output moved into an optional preview of the selected pane. A finished response is no longer presented as a successful task, and stale activity is shown as unconfirmed. (#1446)
• **The wmux MCP tool list is about 9% smaller.** Every tool in `tools/list` carried `execution:{ taskSupport: "forbidden" }`, which is exactly what the protocol assumes when the field is absent, and a JSON Schema `$schema` stamp for draft-07. Without the stamp a client reads a schema as draft 2020-12; wmux's schemas use no keyword whose meaning differs between the two drafts, so they read the same either way. wmux no longer sends either field. Tool names, descriptions, parameters and behaviour are unchanged. Each session pays roughly 7 KB less context for the full profile and about 4 KB less for the core and commander profiles. (#1448)
### Fixed
• **Fleet no longer shows hook-driven active turns as idle.** Fleet now reads the same turn and liveness signals as the sidebar, keeps the selected pane across live reordering, and leaves typing focus in the search field while results change. (#1446)
• **The phone no longer offers desktop features the daemon cannot serve.** A
daemon running without the desktop app still told the phone, in
`/api/config`, that quick commands, workspace creation, account switching and
the workspace browser were available, because it checked that the desktop
bridge was wired rather than that the desktop app was attached. The phone
showed those features, and every one of them failed with `503
desktop-unavailable`. The flags now use the same availability check as the
routes, so they are true only while the desktop app is attached at the time
of the request. (#1450)
### Security
• **A device removed or made read-only mid-request can no longer answer an
approval.** `POST /api/approvals/:id` checked the phone's credential only
when the request started. A device revoked, or narrowed to read-only, while
its answer was still arriving could |
| 3.58.0 | 19 de setembre del 2026 | — | 64 bits EXE Notes de la versió### Added
• The main window now remembers its size, position and maximized (or macOS fullscreen) state across launches, including the relaunch after an auto-update. A saved rectangle that no longer fits any connected display — monitor unplugged, laptop undocked, resolution changed — is discarded in favour of the default size rather than restoring the window off-screen.
• Remote agents now appear in Fleet View and the titlebar vitals chip, with the
same host origin badge the sidebar roster shows. They stay out of the deck's
Fleet roster, which lists only agents this desktop can drive directly.
• Desktop notifications for remote agents. A desktop attached to a remote host now raises a notification when a remote agent finishes a turn or starts waiting for input, instead of only showing it on the pane. The main process holds one `/api/events` subscription per attached host and routes its events through the same notification path as local ones, so the global settings, per-category mutes, idle suppression and dedup all apply unchanged; the host label prefixes the title. Reconnects replay nothing, so a dropped connection never produces a burst of banners.
• **The lock-screen Live Activity keeps up even after the iOS app is closed.** The approval counter on the lock screen used to update only while the wmux app was alive in the background; once iOS or you closed it, the numbers froze. The daemon now drives the activity itself over APNs:it starts one when something needs your approval, updates it as approvals arrive or are answered, and ends it when the last one is done. A burst of changes goes out as one update, and updates carry only counts — how many approvals are pending, how many panes are blocked and for how long, and how many agents are running — plus the daemon's name. The push relay can read those counts; it still cannot read any notification text. A phone paired to an older daemon keeps updating the activity locally, as before. Requires the matching iOS app update. (#1411)
• **Resume chip for remote-terminal tabs.** A tab mirroring a session on a
paired host now offers the same resume affordance a local tab has:the
conversation id, the exact `--resume` line, and a click that types it into
the remote pane. Continuing an agent session on another machine used to mean
finding the id on that machine and retyping it by hand. The host publishes
only what the chip needs — agent, conversation id, whether the recorded
working directory still matches, and the recorded permission mode — and never
the path to its own transcript file. The "never type into a live agent" gate
travels with it, so the chip stays hidden while the host says the agent is
still running, and the command is typed without a trailing Enter, exactly as
locally. The chip is not offered on a host serving without `--allow-input`,
which refuses every write anyway; a host running an older build simply shows
no chip.
• **A truncated snapshot can now be continued instead of re-read.** When
`browser_snapshot` or `browser_smart_snapshot` has more page than fits one
result, it ends with a continuation token — pass it back as `cursor` and the
next lines of the *same* capture come back. No second read of the page, so
nothing moves under you and the ref numbers stay the ones you were already
holding; before this, the only ways past the cut were a narrower `selector`/`q`
or a bigger budget, and both re-captured the page and re-minted every ref.
Windows never split a line, and paging on until `(end of capture)` is how you
know you have read it all. A capture is retired by the next snapshot of that
surface, by a navigation, or after five idle minutes, and a cursor into one
that is gone says `cursor_expired:` rather than quietly serving a stale page.
(#1413)
• **Every browser tool that acts on a page now says whether its action reached
it.** A click, type, fill, key press, hover, drag, select, scroll, navigation,
upload, download or dialog handler ends its result with two machin |
| 3.55.0 | 14 de setembre del 2026 | — | 64 bits EXE Notes de la versió### Added
• Per-site memory (`browser.siteMemory.enabled`, on by default):wmux now keeps a per-workspace, per-domain record of what went wrong on a site. This release lands the store, the RPC surface and the Settings toggle; the hooks that write and read it follow. Records live under `~/.wmux/site-memory/<workspace>/<domain>.json`, are forgotten after 60 days without a repeat and deleted after 180, and an entry that looks like it carries a credential, an email address or a card number is refused outright rather than masked. Turning the setting off stops both recording and serving, while deleting what was already recorded keeps working.
• Browser tools now fill and read per-site memory. A replay that stops files the step it failed on against the site it was recorded for; a navigation that never reaches its host records why; a successful replay just counts. The next time the browser lands on that site, a short `[site]` block says what went wrong there before — capped at four lines and 600 bytes, and carrying no tool call to run, because the point is what not to expect.
• `browser_replay {action:"note", note:"..."}` writes one line to remember about the site you are on. It needs no live page, and refuses a line that looks like it carries a credential.
• Note that the replay half of this only applies on the chrome browser backend, since the builtin webview cannot run a saved flow at all; navigation failures and notes are recorded on either backend.
### Changed
• **MCP `tools/list` diet**:15 tool names were dropped from every profile's listing without losing capability — each stays callable via `tools/call`. `a2a_task_send` is now an unlisted alias of `send_message`; seven `browser_repl` sub-step tools (`browser_navigate_back`, `browser_hover`, `browser_drag`, `browser_select`, `browser_scroll_into_view`, `browser_highlight`, `browser_dialog`) are unlisted (still reachable inside a `browser_repl` snippet, whose description now carries their argument cheat sheet); and the pre-merge names `browser_session_{start,stop,status,list}`, `pane_{set,get}_metadata`, and `pane_unstash` are unlisted in favor of the merged `browser_session {action}`, `pane_metadata {action}`, and `pane_stash {restore:true}` tools. The unlisted pre-merge names remain callable for one release and will be removed afterwards. The `tools/list` payload shrank from 78,089 to 71,367 bytes on the default (full) profile and from 48,566 to 45,804 bytes on `--core`; the commander profile shrank from 56,059 to 53,297 bytes.
### Fixed
• **WSL panes keep their project and Claude conversation after restart.** Linux working directories are validated inside the selected WSL distribution and restored after Bash startup files. Per-pane Claude hooks capture the exact session ID for Resume, including when several panes share a project. The distro picker is honored for new panes; recovery retains the pane's resolved distro and Linux user. (#1263)
• Cold WSL starts no longer block the daemon. Failed recovery keeps the pane and scrollback with an error and a Retry control, including across further restarts.
• A pane restored on demand after exceeding the startup recovery limit now comes back like any other recovered pane on every platform:supervised commands resume their exact Claude session, supervision is re-armed, and the restored state is saved immediately.
• `repl_run`, `repl_reset`, `repl_sessions` and `browser_repl` now reject an
unknown option instead of silently dropping it. The error names the key that
was not understood and the ones that would have worked — for example
`unknown option "timeoutMs"; valid:code, session, timeout, cwd` — so a call
written against a misremembered option fails visibly rather than running under
a default and returning a result that looks like it honoured the request.
• MCP tools whose results the caller cannot size (console rings, network logs, full scrollbacks, page-produced JSON) could dump megabytes into the caller's context in one c |
| 3.53.0 | 12 de setembre del 2026 | — | 64 bits EXE Notes de la versió### Added
• **`wmux setup-hooks` now installs the Codex hooks bridge — and never pretends writing it was enough.** The bridge that reports Codex turn boundaries as facts instead of screen-scraping is wired into the installer at last:the script lands at the stable managed path and a marker-bracketed `[[hooks.*]]` block is appended to `~/.codex/config.toml`. Because Codex silently refuses to run a hook the operator hasn't trusted, the flow is approve-then-verify: the command says **WRITTEN ≠ INSTALLED** and tells you to approve the hooks inside Codex, and `wmux setup-hooks --status` keeps reporting `WRITTEN but NOT trusted` until the bridge has actually fired after the block was written — the only honest definition of installed. The installer refuses outright when the local codex-cli is below 0.141.0 (older builds accept the config and silently fire nothing), when your own `[[hooks]]` entries occupy the config, or when a hand-pasted wmux block can't be bounded safely. (#1236)
• **Snap running panes to a layout** (#1237):the pane ⋮/right-click menu and the command palette can now re-fit the *running* panes into a saved layout template (built-ins: 2 Columns, 2 Rows, 3 Columns, Main + Side, 2x2 Grid) instead of replacing them with empty panes. Sessions keep their identities, tabs and names; surplus panes are stashed (still running, listed in the sidebar) rather than killed, and a snap that would lose unsaved editor/diff work is refused with an explanation.
• **Double-click a pane divider to even out the split** (#1233):double-clicking the divider between two panes splits their combined space evenly between them (a two-pane split snaps to 50/50 in either direction). In groups of three or more panes, only the pair flanking the clicked divider is affected.
• **Seen/unseen distinction for blocked agents in the roster** (#1176):an agent blocked on a question you have already looked at keeps its red dot but stops glowing, distinguishing triaged from untriaged blocked agents across workspaces. A newly asked question glows again; the red dot itself never clears while the agent is still blocked.
• **Remote agents appear in the workspace roster** (#1163):agent sessions running on an attached remote host now count in the roster like local ones, with a live status dot, an origin glyph, and the host name in place of the local pane coordinate. The remote host exposes per-session agent metadata over its API (additive — older hosts and desktops degrade gracefully), and unknown statuses from newer hosts are dropped rather than misread.
• **Choose which WSL distro the WSL terminal boots into** (#1103):when the default terminal is WSL and more than one distro is installed, a distribution picker (Settings → Terminal) lists them all — Docker Desktop distros sorted last — plus the system default. The choice applies to every WSL pane in both local and daemon mode; if the chosen distro is later uninstalled, new panes fall back to the system default.
• **Detached sessions list in the sidebar** (#1101):daemon sessions that are still running but no longer belong to any pane (they survive closing a pane or quitting the app by design) are now listed under the workspaces — click a row to bring the session back as a live pane, or kill it from the row. Empty by default and invisible when unused.
• **Rename and color-tag attached remote workspaces** (#1086):remote rows in the sidebar now support renaming (right-click → Rename, or double-click) and a color tag, matching local workspace rows. Both are kept locally as aliases on the attachment — the remote host still owns the real name, and a rename made on the host shows up behind your alias.
• **Locale drift advisory in CI** (#1037):a report that lists translation keys whose English source changed after the translation was written — the drift class the coverage lock cannot see. Advisory only: findings are printed for a human to judge and never fail the build. Run locally with `node scripts/locale-drift-rep |
| 3.52.0 | 9 de setembre del 2026 | — | 64 bits EXE Notes de la versió### Added
• **Codex approval pauses are now reported by a hook instead of a screenshot guess.** The one Codex lifecycle event wmux could never measure — `PermissionRequest`, the moment a Codex pane stops and shows "would you like to run this command?" — finally fired under a lab rig (interactive TUI driven in a PTY against a stub model endpoint), and the hooks bridge now maps it to the same "needs a human" state the approval screen-regexes produce. A pane whose operator has trusted the hook gets the fact; the regexes stay as the fallback for everyone else. The captured payload confirmed Codex even names the tool the way Claude does, and the user-facing justification it carries never leaves the bridge. (#1231)
### Fixed
• **Ctrl+C on Dvorak (and other non-QWERTY layouts) now interrupts the pane.** xterm.js encoded Ctrl+letter from the physical QWERTY key position, so a Dvorak Ctrl+C arrived as Ctrl+I and Claude would not shut down. The control byte is now taken from the letter you typed. Hangul / IME copy still matches the physical C key when the IME has mangled the letter. (#1228, #1227)
• **Shift+Enter in a Codex pane on Windows inserts a newline.** wmux always sent the kitty form of Shift+Enter, which Codex does not speak — it asks for win32-input-mode instead, and the kitty byte landed as Escape plus junk. The pane's own output is now watched for that negotiation, and Shift+Enter is encoded the way Codex asked. Claude Code is unchanged:it never announces kitty, and still gets the kitty byte it already understood. (#1228, #1152)
• **Pasting an image into a shell that used to be Claude no longer silently drops it.** Leaving a Claude session kept the pane labelled as Claude, so the default image-paste route sent Claude's own paste key into readline and the screenshot vanished. Auto now takes the file-path route once the TUI has left the screen (or the agent process is known dead), and the stale agent name is cleared. (#1228, #1210)
• **Legacy-traffic audit now counts only external-wire callers.** The shadow log and trust-DB legacy records exist to show which no-`clientName` integrations are still calling before the grandfather lane closes (#1111, announced for 2026-09-30). They were also counting wmux's own renderer bridge and plugin host, which send no `clientName` by design — on a dogfood box that noise was ~636k of the ~639k recorded calls (`events.poll` 445k, `task.mission.list` 191k), drowning the signal the close decision relies on. Both audit channels now use the same wire-provenance check the permission lanes use, so anything new in `shadow-rejections.log` is a real external caller. (#1229)
• **An idle pane no longer keeps a ghosted frame until you select its text.**
The final repaint after a stream of output could itself race on the GPU and
leave stale pixels on rows it had just marked clean — and once the pane went
quiet, nothing ever repaired it:focus doesn't re-fire on a pane you're
already looking at, and repairs were only scheduled while output flowed or on
workspace switches. Selecting the text fixed it instantly (the buffer was
always correct), which is what made it so annoying to live with. A pane now
schedules one more verification repaint a couple of seconds after output
settles, so a raced final paint self-heals instead of haunting the pane — and
a pane that gets split or dragged right after a command finishes heals too.
• **Long turns on signals-only installs no longer lose the agent-status veto half an hour in.** The 30-minute hook-authority window was quietly kept alive by the permission gate, which reports on every tool call; the slimmer `--signals-only` profile installs no such hook, so a turn running past 30 minutes handed the pane back to the screen detector — whose always-visible footer reads as "waiting", lighting the roster's red dot and the "N need you" roll-up for an agent that was still working. Authority is now a death backstop rather than a freshness demand:a bridge that only ever rep |
| 3.51.0 | 5 de setembre del 2026 | — | 64 bits EXE Notes de la versió### Added
• **Pasted screenshots can reach the agent as real images.** Pasting an
image-only clipboard into a pane used to write a temp PNG and type its path —
the only route an agent ever saw. Claude Code reads the clipboard itself when
it receives its image-paste key, so it now gets a real inline image instead of
a file path. Settings › Terminal › Image paste picks the route:Auto (the
default) uses it for panes running an agent known to read the clipboard, and
falls back to the file path everywhere else. Pasting text is unchanged. (#1209)
• **Optional:put the workspaces that need you at the top of the sidebar.** A new Appearance setting, "Needs-you rows first", lifts every workspace whose agent is blocked on you to the top of both the sidebar list and the collapsed rail. It is off by default, because a list that reorders itself while you are scanning costs more than the scan it saves. Turning it on changes the display only — Ctrl+N still numbers workspaces by their real position, and the stored order is untouched. Drag-to-reorder is paused while it is on, because a drop aimed at the order you can see would land at the order underneath it.
• `browser_type` takes a `selector`, for an element neither snapshot handed out a number for. It is CSS on every transport — a Playwright engine prefix (`text=`, `xpath=`, `>>`) is refused rather than accepted on one lane and not the others — and it must match exactly one element, the same uniqueness rule a ref carries.
• `browser_type` takes `newline:'enter' | 'shift-enter'`, which splits the text on `\n` and presses a real key between the lines instead of inserting a newline character a single-line input or a rich-text editor drops. Default stays `literal`, today's behaviour. If a keypress submits the field, the remaining lines are not typed into whatever the next page focuses: the type stops and reports how many lines went in.
• `browser_snapshot` takes `q`, keeping only the nodes that match it (case-insensitive substring, or `/pattern/flags`) plus their ancestors — a way to ask a 250-option listbox one question instead of reading it whole.
• Task ledger:a status log keyed by WorkTask id (`~/.wmux/task-ledger.jsonl`, WMUX_DATA_SUFFIX-scoped) recording `working → input_required / review_requested → completed / failed / cancelled` with compare-and-swap revisions, actor authorization and a gate-pass requirement for `completed`.
• MCP:`ledger_update` (every profile) lets a fan-out worker record `review_requested` / `input_required` on its own task; `ledger_list` is a commander-only tool (registered only under `--commander`, never in the full or core profile) that shows the brain the tasks it owns. Fan-out prompts now tell workers to report through the ledger instead of a chat "done".
• Orchestrator:`deck.ledgerGate` (default off, `~/.wmux/deck-ledger-gate.json`) makes the brain's Stop gate hold a turn while the ledger lists open tasks it owns, with the existing consecutive-block cap and hysteresis; while on, `deck_ask_decision` shows the human the open-task list.
• Every ledger transition is posted to the task's mission channel as `[ledger] <task> <from>→<to> <by> <summary>`.
• **An orchestrator can now finish the tasks it starts.** Fanning out could open
N isolated tasks, and then nothing:running a task's completion gate, taking
its changes back into the parent repository, opening its pull request and
closing it were all reachable only from the desktop UI, so a supervising agent
could do nothing but ask you to click four times per task. It can now do all
four itself, and read a task's git status, recent commits and PR state as data
instead of guessing from a terminal screen. It can also stop a gate that is
still running, rather than waiting out a hung test suite for fifteen minutes.
• **Closing a task or opening its PR asks you first.** Those two are the ones
nothing can take back — one removes a git worktree, the other pushes a branch
to your remote — so each raises the same app |
| 3.50.0 | 2 de setembre del 2026 | — | 64 bits EXE Notes de la versió### Added
• **Built-in shortcuts can be switched off.** Every advertised row in Settings → Shortcuts now has a checkbox; unchecking it fully unbinds the combo and the key reaches the terminal instead — Ctrl+T then opens Codex's own transcript rather than a new wmux tab. Custom keybindings rebound onto a disabled combo still fire, and the setting survives restarts.
• **The `core` MCP tool profile can now be selected:`wmux mcp register --profile core`.**
The profile itself shipped earlier, but nothing could actually choose it — every
registration path wrote the full entry regardless. `core` drops the `browser_*`
family, cutting roughly 27 KB of schema off the `tools/list` an agent reads
before it does any work; it is an optimization, not a permission boundary, so a
core-mode agent keeps exactly the authority an ordinary one has. Use it for
hosts doing terminal, pane, workspace, channel, and delegation work that never
touch the browser. `--profile full` moves a host back.
The default is unchanged and stays `full`:the browser tools are first-class,
and an agent driving the workspace browser works with nothing to wire up
precisely because the default registration carries them.
• **`browser_repl`:drive the browser through many steps in one tool call.**
A snapshot, a `refs.find`, a click, a wait and a text extraction used to cost an
agent five round trips, each one re-reading a page of tool output. The new
full-profile tool runs a JavaScript snippet instead, where every allowed
`browser_X` tool is `await browser.X(args)` with its usual arguments. Snapshot
results come back with the refs already parsed, a failed step throws a
catchable error, `console.log` is captured, and the run's call ledger (tool,
redacted arguments, timing, browser events) is printed with the result so the
agent still sees what happened. State survives between calls; a snippet that
overruns its timeout has its runtime terminated and the next call starts fresh.
The snippet runs in a worker thread and every browser step goes through the
existing tool handler, so automation leases, password redaction, ref maps and
the action trace behind `browser_replay` all behave exactly as they do for
direct calls. One thing does change:approving a single `browser_repl` call
covers the 21 tools it exposes (navigate, navigate_back, tabs, click, type,
fill, press_key, hover, drag, select, scroll, scroll_into_view, snapshot,
smart_snapshot, extract_text, extract_data, wait, console, highlight, resize,
dialog). Tools with a heavier footprint — `evaluate`, `screenshot`, cookies,
storage, downloads, uploads, PDF, tracing, replay and surface lifecycle — stay
separate calls. (#1177)
### Changed
• **`browser_smart_snapshot` returns a diff, and its refs hold still.** The
tool re-sent its whole indexed listing on every call, which on an
act-then-verify loop is the same few hundred lines over and over. A repeat
call now returns only what moved, against the same baseline machinery
`browser_snapshot` uses — with the same fallback to the full listing when the
diff stops being a saving, and a first line that always says which of the two
you got. Pass `full:true` for the complete listing.
What made that possible is a fix worth having on its own:smart refs were a
running count over the page, so one element appearing above another
renumbered it and everything after it. Replaying a ref you were given a
moment ago clicked the neighbouring element instead, and said nothing. A ref
is now tied to the element itself, so it means the same thing until that
element goes away — and it never comes back naming a different one. Clicking
by `smartRef` against a live page was broken outright and now works, and a
ref that no longer names one element on the page you are looking at — the
page navigated or reloaded under it, the element went away, several elements
now answer to the same description, or the click is aimed at a different tab —
is refused with an explanation instead of clicking whatever moved in |
| 3.49.0 | 28 d’agost del 2026 | — | 64 bits EXE Notes de la versió### Added
• `browser_snapshot` now returns a compact diff against the previous snapshot of the same page when that is smaller (`full:true` forces the complete tree), and accepts `selector` to scope the snapshot to a subtree and `filter:"interactive"` to strip non-interactive nodes.
• Browser tool results now report page lifecycle changes inline — navigations (including SPA route changes), page loads, and tab closure — including changes the call itself caused, so a navigation is reported on the very result that triggered it and agents no longer need to poll for page state.
• New `chrome` browser backend (Settings → Browser):wmux launches a dedicated real-Chrome instance with its own persistent profile — sign in once and logins stick, fully separate from your daily browser — and agents get the full automation toolset against it. Sites that block embedded browsers (e.g. Google sign-in) work normally there.
• Each workspace can bind its own Chrome profile (workspace card → right-click → Chrome profile):separate logins per workspace, so one workspace can automate account A while another uses account B.
• Bind a workspace to "Live Chrome" to let its agent work inside your own running browser — your real tabs and logins — using Chrome 144+'s official remote-debugging consent flow (enable once at chrome://inspect, Chrome asks permission on every connection).
• Remote workspace attach:"New workspace on this host" in the Attach Remote modal bootstraps the first pane of a brand-new workspace on a paired remote daemon — previously only a sibling pane on a workspace the desktop app had already created could be added.
### Changed
• The workspace right-click → Chrome profile submenu now appears only when the browser backend is `chrome`. On `builtin` or `external` a profile binding changes nothing, so the menu no longer offers a choice without an effect — and the per-workspace profile-list lookup at boot is skipped there too.
• Inline browser lifecycle events are now attributed to the tool call that caused them:the lifecycle ring is drained again after each tool body, so a click that navigates (or `browser_navigate` itself, which now reports events like every other browser tool) shows the navigation on its own result instead of one call late. A lone `navigated` that merely repeats the URL the result already states is suppressed; redirect hops stay visible.
### Fixed
• **Replayed terminal history no longer relies on a timing window.** wmux now
labels replayed daemon PTY data at its source, authenticates its in-band
boundaries, and keeps replay-only control sequences muted across pane
adoption without suppressing live terminal behavior. (#1062)
• Chrome backend:a Chrome left running by a crashed wmux session is now adopted on the next use instead of bricking the backend on its profile lock — instances launch with an ephemeral debugging port recorded in the profile, which is what makes the recovery path actually able to find them.
• Live Chrome:agents can now actually drive pages in your attached live Chrome — both tabs wmux opened and your pre-existing tabs picked from the tab list. Previously only opening and listing tabs worked.
• The browser-backend setting description now covers the Chrome option (and points at the per-workspace profile menu) in Korean, Chinese, and Polish, not just English.
• `browser_snapshot` no longer silently ignores `filter:"interactive"` and `format:"aria"` on its DOM-listing paths. The filter now actually strips the heading block wherever the DOM listing is used — the background-surface fallthrough, the `selector` path, and the RPC fallback — and `aria`, which has no DOM-listing equivalent, now says so with a note instead of returning the default listing unlabeled. (#1066)
## What's Changed
• feat(browser):snapshot auto-diff, selector scoping, inline lifecycle events by @openwong2kim in https://github.com/openwong2kim/wmux/pull/1063
• feat(browser):'chrome' backend — dedicated real-Chrome instance ov |
| 3.48.1 | 27 d’agost del 2026 | — | 64 bits EXE Notes de la versió### Fixed
• **An update that quits and never installs no longer fails silently.** The
install waiter's detached PowerShell process could die before running a
single line of its own script — event-log evidence on a real machine showed
it starting the same second the app called `app.quit()` and never getting
further, consistent with Windows Job Object cleanup catching a "detached"
child that never requested breakaway. The waiter now writes a heartbeat as
its first act, and the app waits (up to 3s) to see it before tearing
anything down. A waiter that never signals costs nothing — no daemon
shutdown, no quit, no install — instead of the app disappearing into an
unexplainable hang. (#1057)
• **A failed update now says what happened, where you can see it.** The
refused-install notice carries the installer's actual refusal reason and
stays on screen instead of fading after five seconds; install errors on
macOS that landed minutes after the click (staging and handoff deadlines)
are no longer silently dropped; and after a failed install the "Install
now" button comes back instead of leaving nowhere to retry from. When an
update left the installation itself broken, the stale "try again" toast no
longer contradicts the boot notice that says to reinstall — including on
the first boot after the reinstall it asked for. (#1058)
• **Clicking Install can no longer quit wmux into a silent no-op.** On
current Windows builds the helper process that runs the installer after
wmux quits could die before executing a single line, leaving the old
version in place with no error and no trace anywhere. The helper's launch
is now verified before wmux commits to quitting — if it cannot be proven
to run, the update is refused on the spot with the app still open — and a
helper that dies partway through now leaves a note that wmux shows on the
next start. (#1059)
## What's Changed
• fix(updater):confirm the waiter actually started before quitting by @p-poppe in https://github.com/openwong2kim/wmux/pull/1057
• fix(updater):surface install failures where the user can actually see them by @openwong2kim in https://github.com/openwong2kim/wmux/pull/1058
• fix(updater):make the install waiter's launch provable, and survivable by @openwong2kim in https://github.com/openwong2kim/wmux/pull/1059
• chore(release):3.48.1 by @openwong2kim in https://github.com/openwong2kim/wmux/pull/1061
**Full Changelog**:https://github.com/openwong2kim/wmux/compare/v3.48.0...v3.48.1 |
| 3.46.0 | 22 d’agost del 2026 | — | 64 bits EXE Notes de la versió### Added
• **`wmux setup-hooks --signals-only` installs the lifecycle signals without
the per-tool-call permission gate.** The remote-approval gate is a wide
`PreToolUse` hook, so Claude Code spawns the bridge on every single tool call
— ~120 ms on Windows 11, of which ~85 ms is bare `node` startup. That cost
cannot be optimised away once the hook is registered, and `gatedTools:[]`
does not help:a policy of "gate nothing" still spawns the process that asks.
It buys nothing for a terminal-only operator either, because both things the
wide hook does need a web surface — approvals arm only under
`wmux web --allow-input`, and the tool-name liveness it feeds is fanned out
only to web clients. `--signals-only` installs the turn-boundary signals and
the approval-card pair and stops there; `--with-gate` puts the gate back. The
profile is derived from `settings.json` rather than stored beside it, so a
bare `wmux setup-hooks` — the app-update refresh and the in-app install
button included — keeps whatever is already installed instead of quietly
re-adding the gate.
• **`wmux web --allow-input` now says when the permission-gate hook is
missing.** Enabling input is what arms the gate, so it is the only place that
can catch a signals-only install:without the hook no tool call ever raises
an approval, and nothing else reports it — the phone simply never rings.
`wmux setup-hooks --status` also stops calling an absent gate a defect when
the signals-only profile is the reason it is absent.
• **A `Matrix` terminal palette** — phosphor green on green-tinted black, in
Settings → Terminal Palette. Green carries the identity (foreground, cursor,
the green slot and a green-cast white), but red and yellow keep their warmth
so a failing test, a removed diff line and a warning still read as
themselves, and blue/cyan/magenta are separated on the hue wheel rather than
collapsed into green, so `ls` can still tell a directory from an executable.
### Changed
• **The agent roster spends its width on the name, not on repetition.** In a
workspace where every session runs the same agent, the vendor name is no
longer printed on each row — it returns as soon as a workspace mixes vendors,
which is when it answers something. Polish status labels lost their "Agent "
prefix (the row already names the agent) and gained the missing
awaiting-input label, which had been falling back to English.
### Fixed
• **A pane reports that it is working when the agent starts a turn by itself.**
A background task finishes, the agent picks up and works for a minute — and
the pane kept wearing the previous turn's `complete` for the whole thing,
because the only two things that could start a turn were you pressing Enter
and a hook that a plugin-less install does not wire. Byte activity now counts
while a pane is settled, held back by a cool-down after the turn end, by your
own keystrokes still echoing, and by a resize still repainting. A pane waiting
on an approval is left alone:only answering it retires a question.
• **A pane's own overlays can no longer paint over app chrome.** The pane box
did not contain its layering, so anything inside one — a decoration badge, a
terminal find bar — could land on top of a dialog or an overlay elsewhere in
the app. Panes now stack independently, and the terminal's right-click menu
opens above everything instead of being clipped or misplaced by the pane
around it.
• **"Don't ask again" now sticks on the Claude Code hook-install prompt.**
Dismissing the modal only ever hid it for that process, so anyone who had
decided against installing hooks was asked again on every launch and on every
raise of agent mode. The prompt now carries a durable refusal that survives
restart and upgrade and silences both of those moments. "Later" is unchanged —
it hides that showing, and raising agent mode still warns you that lifecycle
signals are degraded. Turn prompting back on from Settings → integration
setup. (#968)
• **The in-app update installs again.** C |
| 3.45.0 | 21 d’agost del 2026 | — | 64 bits EXE Notes de la versió### Added
• **The unread-glow dim is now adjustable.** A pane holding an unvisited
notification used to drop to 60% opacity — "the inactive terminal is
shadowed" — which made a session you were monitoring harder to read at the
exact moment it produced output. Settings → Notifications now has an
"Unread pane brightness" slider:100% removes the shadowing entirely (the
colored border glow still marks the unread pane), 60% keeps the classic
look, and the default is unchanged. (#960)
### Fixed
• **The roster no longer reads a working pane as waiting.** Claude Code's
`bypass permissions on` footer is on screen for the whole turn in
bypass-permissions mode, and the detector read every repaint of it as
"ready for input" — which put a false `waiting` on the pane's roster row
and inflated the "N need you" chip while the agent was still working. Once a
pane's hook bridge has claimed that pane's lifecycle, the Stop signal owns the
lifecycle status outright, on both the local and the packaged daemon path.
Approval prompts (`awaiting_input`) are unaffected, and a pane whose hook has
not claimed the lifecycle — no bridge at all, or one that has only announced
itself — keeps the detector as its backstop.
Note for anyone running a mixed pair:on the packaged daemon path the fix
rides the daemon's own arbitration stamp, so an older daemon with a newer
app does not get it until both are updated. (#935, #939)
• **Claude Code panes are detected again.** The Claude gate needed its footer
spelled with literal spaces on a line of its own. The shipping product
(measured on v2.1.235) provides neither:spaces are cursor advances
(`ESC[1C`), so the footer strips to `bypasspermissionson`, and the whole
bottom region — input box, statusline, footer — arrives as one newline-free
run whose rows are placed with cursor-position escapes. The gate therefore
never opened on a real Claude pane, which quietly disabled every Claude
detector pattern, `waiting` and the approval `awaiting_input` regexes alike.
Whitespace is now optional in the footer fragments (the same treatment the
banner pattern already carried) and candidate lines are cut on row-position
escapes as well as newlines. (#935)
• **A freshly launched agent no longer reads as busy.** Hook authority answers
"a bridge speaks for this pane", which is not the same as "the hook has
claimed this pane's lifecycle". A bridge that had sent only `SessionStart`
suppressed the detector's true "ready for input" read, leaving the pane on
the gate's one-shot `running` until its first turn ended. The status veto now
waits for the hook to actually take the lifecycle over. (#935)
• **Korean IME no longer paints the composing syllable over the one just
committed.** Since v3.42.0, typing Korean showed syllables disappearing as
you typed (`대한민국` read `대한국` until the composition ended) — the
candidate-window pin introduced for Chinese/Japanese IMEs dragged the whole
helper container, inline preedit included, back onto committed cells. The
pin now holds only the hidden textarea that anchors the candidate window,
while the visible inline preedit stays on the live cursor, so Korean input
reads correctly keystroke by keystroke and the Chinese/Japanese
candidate-window behavior is unchanged. The IME diagnostic log (now
`ime-anchor2` → `ime-anchor3`) also records mid-composition and
composition-end corrections when they change, so a future report of this
family is self-diagnosing. (#945)
• **The perf gate's frame-budget metrics are judged in frames, so a two-frame
measurement no longer passes by a rounding accident.**
`frameBudget.*.frameDeltaMs.p95` only ever lands on whole frame intervals,
and the old rule — "more than 2x the blessed baseline" — put its threshold
at exactly the top of the two-frame cluster. Every two-frame run passed
because the comparison was strictly-greater, not because it was judged. It
also meant a baseline blessed from a slow run quietly doubled the allowance.
The rule is now "at most one frame interv |
| 3.44.0 | 18 d’agost del 2026 | — | 64 bits EXE Notes de la versióAdded
• Native TLS for wmux web. Use --tls-cert <path> with --tls-key <path> to terminate HTTPS directly when exposing panes without Tailscale. (#775)
• Move panes around your layout. Panes could only be created and closed, so
getting the arrangement you wanted meant splitting in exactly the right order
from the start. Now you can rearrange one you already have:drag the grip in a
pane's tab strip and drop it on another pane's edge to move it there, or on
its centre to swap the two. From the keyboard, Ctrl+B then H/J/K/L
walks the active pane left/down/up/right, and { / } swap it with its
neighbour, mirroring tmux. The command palette carries the four directional
moves as well. Panes keep their names and their scrollback wherever they land.
(#776)
• Settings → Claude integration now opens with a Setup card listing the
hook bridge, the MCP registration, and the usage statusline — each with its
real install state and a one-click install for whatever is missing.
Previously the first-run wizard was the only place these were ever offered,
and skipping it left the CLI as the only way back.
• The first-run wizard now offers the Claude Code hook bridge alongside the
statusline, and shows it as installed when it already is.
• Fan-out can launch in bypass mode without retyping the flag. The Multi Task dialog now offers --dangerously-skip-permissions as a checkbox, shows the launch command it will fire, and prefills the command the last fan-out actually used. The checkbox appears only for Claude Code, the launcher wmux knows that flag for; users of another CLI type their own bypass flag once and it is remembered. A Claude-only flag left behind after switching launchers is called out with a one-click removal.
Removed
• Removed the unused MCP long-poll transport option. sendRpc no longer
carries a separate timeout-and-retry mode for a server-side wait RPC that
does not exist; its production callers continue to use the established
10-second timeout and three-attempt retry path. (#778)
Fixed
• Closing a pane no longer misaligns its neighbours. In a row or column of
three or more panes, closing one left the remaining panes rendering at the
wrong widths — the sizes list still had an entry for the pane that was gone,
so every panel after it was drawn one slot off. Two-pane splits were never
affected, which is why this hid for so long. (#776)
• The workspace mode dropdown no longer runs off the top of the window. It
opens toward whichever side has room and caps its height there, so Off
stays reachable in a short window — autonomy can always be lowered again.
• The orchestrator's "mode is off" note in the deck composer is no longer cut
off. The placeholder shows a one-line form; the full explanation stays on
hover.
• The wizard's statusline offer never appeared:it looked for the preload
bridge at the wrong path and silently hid itself when it came back empty.
Security
• Fail-closed HTTPS restore. Native TLS stores certificate/key paths rather than PEM bytes, validates material before replacing a live listener, and leaves no plaintext listener if persisted TLS material becomes unavailable. Crossing the encrypted/plaintext boundary rotates the operator token and revokes paired-device credentials. (#775)
What's Changed
• feat(web):add native TLS termination by @snowyukitty in #775
• Move panes around the layout (#645) by @openwong2kim in #776
• Keep the mode menu and the composer note on screen by @openwong2kim in #777
• refactor(mcp):remove unused long-poll option by @snowyukitty in #778
• Give the Claude integrations a place to live by @openwong2kim in #779
• Add a skip-permissions checkbox to fan-out and remember the launch command by @openwong2kim in #780
• chore(release):3.38.6 by @openwong2kim in #784
Full Changelog:v3.38.5...v3.38.6 |
| 3.38.6 | 3 d’agost del 2026 | — | 64 bits EXE Notes de la versióAdded
- Native TLS for wmux web. Use --tls-cert <path> with --tls-key <path> to terminate HTTPS directly when exposing panes without Tailscale. (#775)
- Move panes around your layout. Panes could only be created and closed, so
getting the arrangement you wanted meant splitting in exactly the right order
from the start. Now you can rearrange one you already have: drag the grip in a
pane's tab strip and drop it on another pane's edge to move it there, or on
its centre to swap the two. From the keyboard, Ctrl+B then H/J/K/L
walks the active pane left/down/up/right, and { / } swap it with its
neighbour, mirroring tmux. The command palette carries the four directional
moves as well. Panes keep their names and their scrollback wherever they land.
(#776)
- Settings → Claude integration now opens with a Setup card listing the
hook bridge, the MCP registration, and the usage statusline — each with its
real install state and a one-click install for whatever is missing.
Previously the first-run wizard was the only place these were ever offered,
and skipping it left the CLI as the only way back.
- The first-run wizard now offers the Claude Code hook bridge alongside the
statusline, and shows it as installed when it already is.
- Fan-out can launch in bypass mode without retyping the flag. The Multi Task dialog now offers --dangerously-skip-permissions as a checkbox, shows the launch command it will fire, and prefills the command the last fan-out actually used. The checkbox appears only for Claude Code, the launcher wmux knows that flag for; users of another CLI type their own bypass flag once and it is remembered. A Claude-only flag left behind after switching launchers is called out with a one-click removal.
Removed
- Removed the unused MCP long-poll transport option. sendRpc no longer
carries a separate timeout-and-retry mode for a server-side wait RPC that
does not exist; its production callers continue to use the established
10-second timeout and three-attempt retry path. (#778)
Fixed
- Closing a pane no longer misaligns its neighbours. In a row or column of
three or more panes, closing one left the remaining panes rendering at the
wrong widths — the sizes list still had an entry for the pane that was gone,
so every panel after it was drawn one slot off. Two-pane splits were never
affected, which is why this hid for so long. (#776)
- The workspace mode dropdown no longer runs off the top of the window. It
opens toward whichever side has room and caps its height there, so Off
stays reachable in a short window — autonomy can always be lowered again.
- The orchestrator's "mode is off" note in the deck composer is no longer cut
off. The placeholder shows a one-line form; the full explanation stays on
hover.
- The wizard's statusline offer never appeared: it looked for the preload
bridge at the wrong path and silently hid itself when it came back empty.
Security
- Fail-closed HTTPS restore. Native TLS stores certificate/key paths rather than PEM bytes, validates material before replacing a live listener, and leaves no plaintext listener if persisted TLS material becomes unavailable. Crossing the encrypted/plaintext boundary rotates the operator token and revokes paired-device credentials. (#775)
What's Changed
- feat(web): add native TLS termination by @snowyukitty in #775
- Move panes around the layout (#645) by @openwong2kim in #776
- Keep the mode menu and the composer note on screen by @openwong2kim in #777
- refactor(mcp): remove unused long-poll option by @snowyukitty in #778
- Give the Claude integrations a place to live by @openwong2kim in #779
- Add a skip-permissions checkbox to fan-out and remember the launch command by @openwong2kim in #780
- chore(release): 3.38.6 by @openwong2kim in #784
Full Changelog: v3.38.5...v3.38.6 |
| 3.38.5 | 2 d’agost del 2026 | — | 64 bits EXE Notes de la versióAdded
- The daemon can project a pane's transcript as structured turn events.
Each pane's scrollback can now be read as a sequence of turns (who spoke,
what was asked, what ran) instead of raw terminal bytes. This is the daemon
half of #655 — groundwork for clients that want to render a conversation
view rather than a terminal mirror. (#771)
Changed
- The workspace list fits more of your fleet on screen. Rows are tighter,
and each running agent in a selected workspace now sits on a single line
(name, pane, and status together) instead of a stacked, boxed card. When an
agent is actually waiting on you, its question still opens on a second line
in red so you can see what it needs at a glance.
Fixed
- Long branch names in the sidebar are no longer cut short. Each
workspace row shows its git branch under the name, and that label used to be
capped at a fixed width, so a branch like feat/deck-new-session was
truncated to feat/deck-n… even when the row had room to spare. The label
now uses the full width of its line and only elides when a genuinely long
name would overflow, keeping the git status and PR badge right beside it.
(#767)
- Answering an agent's question at the desk now clears it from your phone
right away. When Claude Code asked a question and you answered it in the
terminal on the Mac, the phone's approval inbox kept showing it as pending —
badge and all — until the whole turn ended, because nothing told the daemon
the question had been answered locally. The Claude bridge now reports the
moment an AskUserQuestion completes (agent.input_answered), and the
daemon expires the request immediately with reason answered-locally. The
completion signal is also exempt from the PostToolUse activity throttle, so
a fast answer cannot slip through the 2.5 s window unreported. (#773)
What's Changed
- fix(terminal): rebuild the shared glyph atlas at wake boundaries by @openwong2kim in #768
- feat(sidebar): compress workspace row density, one-line agents, full-width branch by @openwong2kim in #767
- Project a pane's transcript as structured turn events (daemon half of #655) by @openwong2kim in #771
- fix(approvals): expire pending requests when user answers locally by @openwong2kim in #773
- refactor: remove dead approval request IPC by @snowyukitty in #765
- chore(release): 3.38.5 by @openwong2kim in #774
Full Changelog: v3.38.4...v3.38.5 |
| 3.38.4 | 2 d’agost del 2026 | — | 64 bits EXE Notes de la versióAdded
- The multiview grid can be stacked vertically. Settings → Layout now has a
Multiview arrangement control with three choices. Auto keeps the old
behavior — two workspaces side by side, four in a 2×2 grid, five or more in
three columns. Columns puts every workspace in one row, and Rows stacks
them in a single column, which is what you want on a tall display or when the
tiles are agent transcripts that read better narrow. Before this, four
workspaces were always 2×2 and there was no way to say otherwise. Arrow-key
navigation between tiles follows the arrangement you picked, and the choice
survives a restart. (#748)
Changed
- Critical-action notifications now show the matched terminal line. The
critical attention event carries matchedLine — the printed terminal
output that tripped the pattern, sanitized and capped — so a heads-up can
say git push --force origin main instead of just "git push --force". (This
is the text the terminal displayed, which may quote a command rather than run
one; it is not proof the command executed.)
- Documented that the critical signal is notify-only: it fires on printed
output, not on a pending action, and is not something a remote surface can
answer. Approvals remain the only answerable signal.
Fixed
- Scoped MCP browser fallbacks to their calling workspace. Browser tools no
longer let automation leases, CDP discovery, or RPC fallbacks select another
workspace's webview when the intended target is missing or ambiguous. (#749)
- Closing a workspace no longer leaves multiview in a broken state. Closing
members of a multiview group from the sidebar could leave the app showing a
single tile still wrapped in multiview chrome, with no way back except
Ctrl+Shift+G. The closed workspace is now dropped from the group, and the
group disbands once fewer than two members remain. (#753)
- Ctrl+click on the workspace you are looking at no longer closes the whole
grid. Removing the active workspace from a multiview group took every other
tile with it. Focus now moves to a neighbouring tile first, the way the tile's
own ✕ button already behaved. (#753)
- Resizing while text is selected no longer leaves the terminal at the wrong
size. If you selected some output and then resized — dragging a split
separator, toggling the sidebar, resizing the window — the terminal and the
shell behind it stayed at the old dimensions even after you cleared the
selection. Output wrapped at the wrong column and full-screen programs drew
against stale dimensions until something else happened to resize the pane. The
deferred resize now runs as soon as the selection goes away. (#754)
- LanLink halved the disk writes a received message costs. Each inbound record used
to force two full rewrites of the peer file, and on Windows every rewrite shelled out
to whoami.exe and powershell.exe to re-apply the owner-only file permissions — a
step measured at seconds per call on machines running antivirus, and one that blocked
the whole daemon while it ran, so a peer sending a burst of messages could stall wmux.
The "last seen" timestamp now rides along with the write the record already needed,
instead of forcing one of its own. The remaining write is the replay guard, which has
to be durable; making that one cheap on Windows is still open. (#755)
- Panes no longer flicker and settle black after a WebGL teardown. When
xterm's WebGL addon was disposed (pane hidden, tab switch, font reload) and
an internal step threw mid-dispose, the addon's own "hand back to the DOM
renderer" step was silently skipped — leaving the pane with no renderer at
all. Every render tick after that (cursor blink, scroll, resize) threw, so
the pane flickered and then stayed black until relaunch. Teardown now
verifies a renderer survived and restores the DOM renderer itself when it
did not. (#759)
- Browser navigation no longer reports a transport timeout for a DNS
failure. The navigation guard's DNS lookup was unbounded, so a slow or
unresolvable hostname outlived the call |
| 3.38.3 | 1 d’agost del 2026 | — | 64 bits EXE Notes de la versióAdded
- Phones can reshape a pane they are the only client of. POST /api/sessions/<id>/resize reflows the PTY to the phone's viewport, so a 151-column desk pane stops arriving letterboxed or shrunk past reading — the wrapping happens in the PTY, before any client sees a byte, so nothing on the phone could fix it. A desk client that has the pane attached keeps ownership: the route answers 409 desk-owns-size with the current geometry rather than starting a resize fight the desk's next layout pass would win anyway. Available without --allow-input, like the diff route — it delivers a SIGWINCH, not a keystroke. (#743)
Fixed
- The Schedules panel's "Add schedule" button no longer gets clipped off the right edge of a narrow deck — the create row wraps and its time/repeat controls shrink.
- Scattered wrong glyphs across several panes at once during CJK-heavy sessions. The shared WebGL glyph atlas's page-merge path corrupts sibling panes' cached glyph references when its page pool fills (16 pages on Apple Silicon; Hangul's 11,172 distinct syllables fill it fast); a new guard now rebuilds the atlas coherently for every sharing pane just before that path would run, and repairs within seconds if it ever does. (#741)
- Check for updates now installs the update on Apple Silicon Macs. Pressing it downloaded
and verified the new version and then did nothing at all: no restart, no
error, and nothing on any press after that. Installing asks macOS to close
every window first and only goes ahead once they are all gone, but wmux keeps
its window alive so it can sit in the tray, so the close was cancelled and the
installer waited forever on a wmux that was never going to quit. The signal
that was meant to let those windows go was listening for something that is
never sent to it, so it never arrived. wmux now says so directly and there is
no message left to miss. If installing still fails to restart the app, wmux
stops waiting, brings the window back and tells you what happened instead of
going quiet, and the button works again on the next press rather than
silently refusing for the rest of the session. Updates that were interrupted
no longer leave their downloaded copy behind either, where they had been
piling up at around 120 MB each. (#742)
- The lock-screen Approve button never appeared on any notification. The iOS extension has nothing but the sealed payload, so it reads an absent risk as "unknown" and withholds the affirmative — but the daemon only ever set risk on the critical branch, which is right for /api/approvals and wrong here. Push payloads now always state critical or normal. (#743)
- Two builds of the phone app on one tailnet took turns breaking each other's push. An APNs token does not say which stage minted it and Apple's two hosts reject each other's, so the relay's single APNS_ENV was one answer for every device — the symptom was a BadDeviceToken that traced back to nothing. The daemon now stores the stage the app reported per device and the relay routes on it, falling back to APNS_ENV when a device named none. (#743)
What's Changed
- Keep the schedule Add button inside the deck panel by @openwong2kim in #740
- Self-heal panes when the shared glyph atlas merges pages by @openwong2kim in #741
- Let the macOS in-app update actually install by @openwong2kim in #742
- 폰 계약: PTY resize 라우트, push risk 상시 명시, APNs 스테이지 기기별 라우팅 by @openwong2kim in #743
- chore(release): 3.38.3 by @openwong2kim in #744
- docs(changelog): 3.38.3에 빠진 #743을 넣는다 by @openwong2kim in #745
Full Changelog: v3.38.2...v3.38.3 |
| 3.38.2 | 1 d’agost del 2026 | — | 64 bits EXE Notes de la versióAdded
- You can hand a workspace a fresh orchestrator without losing anything
else. A New session control now sits with the other orchestrator
controls at the top of the deck. It retires the current orchestrator and
starts a new one that reads your project files again and takes a fresh look
at your panes, which is what you want once a long conversation has drifted or
a turn has wedged. There was no way to do this before: restarting wmux
deliberately resumes the same conversation, quitting the orchestrator's own
terminal just reopens it on that conversation, and deleting the workspace
takes every pane with it. Your panes, worktrees and conversation history all
stay, and loops and schedules keep running. It asks for a second click before
it commits, and stays available even mid-turn — a stuck turn is usually
exactly when you need it. (#711)
- You can set a dependent child task loose without stopping it. A Detach
from parent action now sits in the context menu of a child workspace that a
fan-out spun up. Detaching releases that task from its parent — the parent
stops tracking it and its mission channel folds away into Archived — while the
workspace itself, its worktree, branch, terminals and running agent all keep
going, now on their own. Before this, a child task was tied to its parent for
its whole life: the only way to end the relationship was to close it, which
tears down the worktree and the work along with it. Detach keeps everything
and simply cuts the leash. The cleanup scanner knows a detached worktree is
still live, so it is never offered up for deletion, and detaching something
twice is harmless. (#715)
Changed
- The orchestrator now runs on the terminal brain by default. The Command
Deck drives your own claude binary in an embedded terminal instead of the
Agent SDK, so it needs no API key and picks up its per-workspace CLAUDE.md
from disk every time it starts. The SDK brain has not gone anywhere: it stays
selectable under Settings › Orchestrator, and wmux still falls back to it
automatically when daemon mode is unavailable. Existing installs move over on
the next launch. The move is reversible and costs no history — each brain
keeps its own conversation, so switching back in Settings picks your SDK
conversation up exactly where it was. (#710)
- The workspace mode now says how Claude is started, not how chatty the
orchestrator is. The three modes never reached the Claude process at all,
so "Off" quietly meant "wakes less often" while the orchestrator kept
running. Now: Off does not start it (and stops one that is already
running), Assist starts it with edits accepted automatically while every
other permission prompt still stops and asks, and Danger — the mode
previously called Auto, renamed for what it does — starts it in bypass mode.
How often the orchestrator wakes on its own is now a separate setting, and
every existing workspace keeps the wake behaviour it already had. (#735)
Fixed
- A pane running a TUI that asks the terminal about its own modes no longer
freezes. opencode probes six terminal modes the moment it starts, and each
probe hit a miscompiled xterm handler that threw. The throw killed that pane's
parser for good: the process kept running and its title kept updating, but the
screen never painted again and every agent read of it came back
RPC timeout: input.readScreen (5000ms) — with nothing to explain why. The
renderer bundle is now built at a target that stops mangling the handler.
(#708)
- Reading a pane can no longer hang. The read path waited on the pane's
parser without a deadline, so a stalled pane took the whole read down with it
and the caller got nothing. Reads now wait a bounded moment and return what
the pane has, which is worth far more than a timeout. (#708)
- The orchestrator model picker now applies to the terminal brain. The
model only ever reached the orchestrator when you typed into the deck
composer, and the terminal brain has no composer — you type into its terminal.
Choosing a model t |
| 3.38.0 | 29 de juliol del 2026 | — | 64 bits EXE Notes de la versióAdded
- Every production dependency's license is now checked before it can ship, and an undetermined verdict fails. wmux distributes signed, notarized binaries, so a GPL/AGPL dependency reaching that bundle creates a source-disclosure obligation that cannot be undone after a release — and nothing was checking. The new gate is deny-by-default: a package passes only if its license is on an explicit permissive allow list. Anything else fails, including the cases automated tooling reports as "no license found" — NOASSERTION, other, UNKNOWN, empty, or npm's SEE LICENSE IN <file>. That is the whole point: automated detection returns "other" for projects whose LICENSE file, when a person opens it, is the GNU General Public License, so a checker that treats "could not determine" as "nothing found" waves exactly that case through green. A third check reads the LICENSE text each package actually ships and rejects a copyleft body no matter what the manifest declares, because the manifest is what lies in that failure mode. Exceptions live in license-allowlist.json, pinned to an exact name, version, and declared license, each with a written reason recording what a human read — a version bump retires the exception and requires a fresh reading. Runs with npm test; node scripts/check-licenses.mjs reports on demand.
- THIRD_PARTY_NOTICES is now guarded against drift. It listed 110 packages while 128 were actually shipping and had not been regenerated in two months, attributing @modelcontextprotocol/sdk at a version no longer installed. The generator gained a --check mode that the test suite runs, so the file can no longer fall behind package-lock.json unnoticed — the same arrangement that already keeps docs/api/reference.md honest.
- An agent can now start a fan-out, not just a human. Fan-out — one prompt split into N isolated tasks, each with its own git worktree, branch, workspace, agent pane and private mission channel — existed only behind the in-app dialog, so the MCP surface wmux exposes to other agents could not reach its flagship journey. The new fanout_start tool does, and channel_mission_list reports back what each task became: status, branch, worktree path, and the workspace it runs in.
What a caller may ask for is deliberately narrower than what the dialog accepts, because the dialog's fields were typed by a human and a tool call's are not. The repository is not a parameter: it is the git top level of the calling terminal's own directory — the pane the request came from, not the workspace it sits in, so a pane next to the caller cannot choose the repository on its behalf — and naming one is rejected rather than quietly ignored. The same directory is derived a second time once the user approves, and the fan-out is refused if it has moved, so the repository named on the prompt is the repository that gets modified. The agent command is likewise not a parameter, because it is interpolated into a shell line. Which workspace owns the tasks — and the caller's name inside the resulting mission channels — is resolved from the caller's verified terminal, and stating one is refused, not overruled in silence. Task count and prompt and title sizes are capped where the request arrives, not only deeper in. And like the existing background-execution path, fan-out is refused outright to anything that did not arrive over the local machine's own socket.
Spawning takes far longer than a single call can wait for, so fanout_start answers as soon as it has accepted the work and you follow it by calling again with the same idempotency key: it reports waiting-for-approval, then running, then the full per-task result. A repeated key never starts a second fan-out — including after a failure, and including long after the result itself has aged out of memory, since a key that has already spawned is remembered as having spawned rather than forgotten wholesale.
Every fan-out started this way asks the user first, and that prompt is not covered by the existing aut |
| 3.37.2 | 27 de juliol del 2026 | — | 64 bits EXE Notes de la versióChanged
- wmux describes itself as the workspace multiplexer for AI agents, not AI coding agents. The panes, channels, worktrees, and browser wmux multiplexes were never specific to agents that write code, and the narrower line kept implying they were. README, the package description, and the Chocolatey summary now say "AI agents"; nothing about what wmux detects or how it behaves changes.
Added
- A phone that is too old to talk to your daemon can now say so. The phone API had no version on it, so once a mobile build ships it is pinned to whatever HTTP surface the daemon happens to serve — and a mismatch would have surfaced as routes failing one by one with no explanation. GET /api/config, the call a client already makes at connect, now reports the protocol the daemon speaks, the oldest one it still accepts, and the release it was spawned from. A client below the floor can show "update the app" instead of a broken screen. Nothing that already works changes: a daemon predating this simply has no version fields, which reads as the pre-handshake protocol, and a phone that ignores them behaves exactly as it does today.
Fixed
- The cold-start perf gate no longer fails the build because CI got a slow machine. The gate compared the median of three boots against a blessed baseline, and its only defence against a noisy runner was to measure again — on the same runner. That covers a spike lasting a second; it does not cover a host that is degraded for the whole job. One was on 2026-07-27: the daemon needed 2.2s just to spawn its Node process and 2.0s to take a file lock, the median landed at 2470ms against a 1207ms baseline, the re-run reproduced it exactly as designed, and main went red over a commit whose entire diff was the length of a web pairing code. The gate now reads the fastest of the boots, because interference is one-sided — a busy host makes a boot slower, never faster — so the fastest one is the sample least polluted by the machine. That run would have read 1442ms and passed; a real regression slows every boot and still trips both thresholds. The median is still measured, still published to the trend, and now reported on its own when it regresses while the fastest boot does not, since a slowdown only some boots hit is worth a look even though it is not worth a red build.
- The "Serve panes to a browser" Start button no longer fails with "tailscale is not on PATH" when Tailscale is installed. On macOS, an app launched from the Dock inherits launchd's minimal PATH, so the GUI could not find a tailscale CLI that worked fine in a terminal — the HTTPS option failed with spawn tailscale ENOENT even with the desktop app installed. The GUI now searches the way a shell would (Homebrew, /usr/local/bin, ~/.local/bin) and falls back to the CLI inside /Applications/Tailscale.app itself, which a stock install never puts on any PATH. wmux web --tailscale in a terminal was never affected.
- A pane no longer goes dead while the shell inside it keeps running. On Windows, node-pty sometimes reports that a terminal exited when in fact only its output socket closed — the code it hands back is empty, and powershell.exe and whatever agent it was hosting are still very much alive. wmux believed the report, marked the pane dead, and walked away, which meant an agent kept burning memory and API quota with nothing left to reach it or shut it down, and the pane came back in your home directory instead of your project. wmux now asks the operating system whether the process is actually gone before believing any exit that arrives without a code. If it is still there, wmux shuts the whole tree down itself — the shell and everything it started — and closes the pane properly, saying so in the log. The exact report from the terminal layer is logged verbatim, which is what the underlying investigation needs. Real exits are untouched: an exit that carries a code, or a signal, still behaves exactly as before. (#646)
- Shells orphaned by that bug are now cleaned |
| 3.37.1 | 27 de juliol del 2026 | — | 64 bits EXE Notes de la versióFixed
- "Check for updates" now works with auto-update switched off. The toggle was wired through the one gate every check passes, so turning background polling off also turned the manual button into a no-op that reported "checking" and went silent — leaving reinstalling as the only way to update. The toggle now silences background polls only; pressing the button is an explicit request and always checks.
What's Changed
- ci: harden GitHub Actions workflows by @snowyukitty in #642
- fix(updater): let a manual check run with auto-update switched off by @openwong2kim in #643
- chore(release): 3.37.1 by @openwong2kim in #644
Full Changelog: v3.37.0...v3.37.1 |
| 3.36.0 | 26 de juliol del 2026 | — | 64 bits EXE Notes de la versióAdded
- See what an agent actually changed before you approve it. An approval prompt on a phone gave you a screenful of terminal and a yes/no button — the agent asked to edit a file and the one thing you needed was what the edit was. wmux web now answers that from the pane's own repository: the changed file list and the full patch, staged and unstaged, read straight out of git. It works on a read-only server, because reading a diff is reading. A pane that is not in a git repository says so plainly rather than looking broken — running in a scratch directory is normal, and only git itself gets to say a directory is not a repository: a git that could not be run at all reports a failure instead of blaming your working tree. Files the agent has just created are in the patch too, which plain git diff never shows. Large diffs are capped at 512 KB so a phone on a train is not made to pull a generated-file commit to answer one question, and if any part of the patch could not be collected the response says so — an empty patch that silently meant "a git command failed" would read on a phone as "nothing changed", which is the one wrong answer to show someone who is about to approve an edit. Two things it deliberately does not trust. It reads the directory the pane was spawned in, not the one the pane says it is in now: the live directory is tracked from terminal escape sequences, which any process running in that pane can emit, so following it would let a program inside a pane point this read at any repository on the machine. And it treats the repository as hostile input, because an agent may have cloned it from anywhere — every git command runs with external diff drivers, textconv filters, filesystem monitors and the whole inherited GIT_* environment disabled, so none of the several config keys and .gitattributes entries that are commands git will execute can execute anything. It also never takes git's index lock, so reading a diff cannot block or break the agent's own commit. At most two diffs are collected at once daemon-wide, and simultaneous requests for the same pane share one answer.
- Open and close panes from the phone. wmux web can now spawn a new pane (optionally in a chosen workspace and directory) and close one, so a phone is no longer restricted to the panes that happened to exist when you left your desk. Both require the server to have been started with --allow-input: an interactive shell is arbitrary execution, and closing someone's pane ends their running build, so neither belongs on a server that promised to be read-only. A pane created this way is a real, monitored, recoverable session — it is not yet drawn in the desktop window's layout. A named workspace has to be one the daemon can actually see a live pane running in: the workspace list belongs to the desktop, and the daemon accepting an unverifiable id would have let a caller file a pane under any workspace it cared to name. The cost is stated plainly in the API docs — a real workspace with no panes open cannot be named until one is — and spawning without a workspace always works.
- Attention events now say how much of a human they are asking for. Every event on /api/events (SSE and the JSON backlog) carries tier: act when someone is blocked on a person — an approval was raised, a critical-risk action fired — and info for a notification, a review-risk signal, or the lifecycle echo of an approval that is already over. Clients were each re-deriving urgency from the event kind, which meant the answer lived in every app instead of in the daemon. The vocabulary is deliberately two plain words rather than one platform's notification taxonomy: the wire states the fact, the client decides what to do about it. Additive — a client that ignores the field behaves exactly as it did before, and the tier is stamped after the payload, so a pane cannot declare its own critical event unimportant.
- An approval that names a destructive action is flagged as such. Approval records gain |
| 3.35.1 | 25 de juliol del 2026 | — | 64 bits EXE Notes de la versióFixed
- The app's web popover can now actually connect a phone. It offered two options and neither worked: the default served only to this machine, so the address it showed was meaningless on a phone, and "Expose to network" reached the phone but then refused to pair, because a device credential never expires and is not handed out over plain HTTP. Worse, the popover advertised a fresh pairing code every ten seconds in exactly that state — you read six characters onto a phone and only the redemption told you it was never going to work. There is now a "Serve over HTTPS (needs Tailscale)" option that sets up the same one-command Tailscale front wmux web --tailscale uses, and when pairing cannot succeed the popover says why and what to do instead of showing a code. If Tailscale is missing or logged out, the popover says which of those it is and links straight to the install page rather than leaving you a URL to retype. Ticking it unticks "Expose to network" and the reverse: tailscale serve proxies to this machine only, so a wildcard bind alongside it is a second and weaker way in, not an addition. "Expose to network" now also says plainly that it serves panes for watching but cannot pair a phone.
- A tailnet address is no longer advertised after its front disappears. The server remembers the HTTPS name it was started behind and puts it back after a restart, but nothing checked whether tailscale serve was still configured — so a tailscale serve reset, a logout, or a tailnet switch left the app showing an https:// address that reached nothing. It is verified now at the moments a human is about to use it (opening the popover, turning the option on, minting a code) and dropped with an explanation when it is gone. Deliberately not checked on the background refresh: that would start a Tailscale process six times a minute for something that only changes when someone acts.
Added
- Devices are named before they are paired, from the desktop. Pairing from the app produced a roster of entries all called "Unnamed device", which makes the one thing the roster is for — revoking a single lost phone — impossible six months later. The pairing code is now shown only after you name the device, and the name is asked for on the desktop, where there is a keyboard, rather than on the phone. Existing paired devices are unaffected, and pairing from the CLI already worked this way.
- Pair a phone by scanning a QR code, with nothing to type. The popover now shows a QR next to the pairing code, and it carries the address and the code together, so a scan finishes the pairing. The address was always the miserable part on a phone — a raw tailnet hostname gets no autocomplete and no search suggestion — so a QR that only opened the pairing screen and still wanted six characters typed would have removed the easy half. The plaintext code stays on screen for a phone that will not scan. The code is stripped from the phone's address bar the moment it is read, so it does not sit in browser history; it is single-use and expires in ten minutes either way.
What's Changed
- docs: withdraw the F1 pipe-transport recommendation by @openwong2kim in #618
- docs(readme): correct the signing, theme and MCP claims, and recapture the screenshots in dark by @openwong2kim in #623
- docs(readme): replace the light header banner with a dark one that matches the product by @openwong2kim in #624
- docs(banner): rebuild the banner with OFL fonts instead of the macOS system faces by @openwong2kim in #626
- Reach your phone from the app: restore the GUI pairing path, and name what you pair by @openwong2kim in #627
- Pair a phone by scanning, with nothing to type by @openwong2kim in #628
- test(daemon): wait for the pipe server to register a socket, not for 50ms by @openwong2kim in #625
- chore(release): 3.35.1 by @openwong2kim in #629
Full Changelog: v3.35.0...v3.35.1 |
| 3.35.0 | 25 de juliol del 2026 | — | 64 bits EXE Notes de la versióSecurity
- The wmux web page now ships a full Content-Security-Policy (#608). The page previously carried only frame protection. It now declares a strict policy — every inline script is allowed by its exact hash (no 'unsafe-inline'), and connect-src 'self' means that even if a rendering bug ever reintroduced an XSS, the injected script could execute but could not send the access token anywhere. The hashes are computed by the daemon from the exact page bytes it serves, so the policy can never drift out of sync with a build. Purely defense-in-depth: there is no known XSS today, and nothing changes for a working session.
Added
- The first-run wizard now offers to enable the Claude Code statusline. wmux setup-statusline — which shows model, context usage, and 5h/7d rate limits under Claude Code's input box — existed only as a CLI command, so app-only users never discovered it. The onboarding wizard now shows an opt-in "Enable statusline" step (macOS and Windows) when Claude Code is detected and at least one settings file can accept the install. It stays strictly opt-in: nothing installs at boot, an already-installed statusline shows nothing, and a user-authored statusline is never overwritten.
- In-app auto-update now works on macOS (Apple Silicon) (#609). Settings → "Check for updates" did nothing on a Mac: the whole updater was gated to Windows, so the only way to move to a new version was to notice a release, download the DMG, and drag it over the old app. macOS (arm64) now follows the same flow Windows has: wmux polls for a newer release, downloads it, pins its SHA-256 against a manifest published by the release pipeline, and installs it on restart — sessions survive, because the daemon keeps running through the swap. Nothing is installed unless the download's hash matches the manifest exactly; on any mismatch or transport error the update is refused outright and the failure is shown rather than silently retried. A build that isn't code-signed (a locally-made one) can't self-update at all, and now says so with a link to the DMG instead of failing silently. Windows behavior, its release assets, and its manifest are all untouched; Linux and Intel Macs still have no in-app updater and are unaffected.
- Pair a phone by name, and revoke that one phone. Pairing used to hand the device the server's own access token, and since that token now survives restarts, every paired device shared one secret — losing a phone meant rotating everybody. You now name a device before pairing it, and it gets a credential of its own. The daemon stores a hash and never the secret, so the roster file is worthless if it leaks or gets mirrored by a cloud-sync engine. Revoking one device cuts its live streams immediately rather than at its next reconnect, leaves every other device alone, and is honest when the write fails: it tells you it could not save the change while still severing the connections, so you know to retry before a restart. An unknown device and a wrong secret give the same answer, so a rejection never tells a guesser which half they got right. wmux web --new-token still means what it always meant — it revokes every paired device along with the old token, and refuses the rotation outright rather than reporting a half-done one if the roster cannot be written. Because a long-lived secret must never sit in a URL, a device authenticates with a header and trades it for a short-lived ticket to open a stream — your browser does this on its own, and the desktop's own token path is unchanged. Pairing is refused outright over a plaintext network bind, naming both ways out rather than just saying no. And the page itself is now served under a content security policy locked to the exact hashes of the bundle inlined into it, so a script injected into that page never executes at all.
- wmux web --tailscale sets up phone access in one command. Reaching a pane from your phone used to mean installing Tailscale, running tailscale serve, then restarting wmux we |
| 3.34.0 | 25 de juliol del 2026 | — | 64 bits EXE Notes de la versióAdded
- Choose your browser backend: built-in panes, or your real browser (#517). A new Settings → Terminal option, "Browser backend", decides where browser opens land. The default (Built-in) keeps today's behavior exactly: an embedded browser pane opens inside wmux and the full automation toolset works on it. Switching to External routes every open — an agent's browser_open / browser_navigate, and your own clicks (the pane's browser button, the command palette, the keyboard shortcut, a workspace's port badge, a link clicked inside a terminal) — to your OS default browser instead. wmux spawns no embedded Chromium at all, so a workspace that opens pages costs wmux zero browser memory, whether the page was opened by an agent or by you. External mode is deliberately fire-and-forget: wmux gets no handle on the opened tab, so tabs aren't tracked, listed, or closable from wmux, and deep-automation tools (click, screenshot, extract, …) fail with a clear "backend is external" error instead of a confusing target-miss — agents are told exactly why and what to use instead. Opens land in your real, signed-in browser, from any workspace — that reach is the point, and the Settings copy says it plainly. The choice is read by the main process at boot (no startup race: the very first open after launch already honors it) and applies immediately when changed.
Fixed
- wmux web notifications now show the message instead of the word "Notification" (#597). When a pane emitted a desktop notification, the banner in the phone browser read the literal string "Notification" and the actual text — "Build finished, 3 tests failed" — was dropped on the floor: the page was reading a field name the daemon never sends. The banner now renders what the pane actually said, for every notification flavor (OSC 9, which carries only a body; OSC 777 and OSC 99, which carry a title and a body), and the parsed notification travels to the browser whole — source, title, body and timestamp — so nothing is lost between the pane and your phone.
- wmux web no longer loses attention events when the connection drops, or while nothing is watching (#598). Approval requests and pane notifications were fired at whoever happened to be connected at that instant and then forgotten: lock your phone, walk through a dead spot, or simply have no browser open, and the alert was gone for good — the pane sat waiting on an answer you were never shown. The daemon now keeps a short rolling record of fleet attention events (the last 100, up to 30 minutes) and serves it on a dedicated stream that survives reconnects: your phone resumes exactly where it stopped, and events raised while you had nothing open are delivered the moment you reconnect. Reloading the page picks up from the same place. When the record can't be lined up with what you already saw — a fresh device, or a daemon restart — you get one "N events while you were away" summary and the affected panes light up in the fleet strip, instead of a stack of banners for alerts you may already have dealt with. Duplicates are suppressed, so nothing is shown twice.
- wmux web now survives a daemon restart, so phone access no longer dies while you are away from the desktop (#596). Your sessions already survived a crash, a reboot, or the one-click update flow; the server that serves them to your phone did not. Nothing recorded that you had turned it on, so the port simply stopped answering, the phone showed nothing but "reconnecting…", and the only fix was to walk back to the desktop and run wmux web again — in exactly the situation phone access exists for. wmux now remembers an explicit wmux web (the bind address, --allow-input, --allow-host, the port) and brings the server back with the daemon, with the same access token, so a browser you left open reconnects on its own with nobody at the keyboard. Carrying the token also fixes the smaller version of this: re-running wmux web to add --allow-host for a tailscale serve front no longer locks out a |
| 3.33.0 | 24 de juliol del 2026 | — | 64 bits EXE Notes de la versióAdded
- wmux web — reach your terminal panes from a phone browser (read-only, local-only by default). A new command starts a small web server, hosted inside the daemon, that serves your live panes to a browser: run wmux web --expose, open the printed http://<tailnet-ip>:7681/?token=… link on your phone (same Tailscale tailnet or LAN), pick a pane, and watch its output stream in real time. It reuses the daemon's own PTY data (initial screen from the same ring-buffer flush the desktop uses, then a live tee of terminal output), so it never fights the desktop GUI for a pane and it keeps working even after you close the desktop app — the agents are still supervised by the daemon. Safe by default on two axes: it is read-only (the browser can watch but cannot type — pass --allow-input to opt in) and it binds loopback only (127.0.0.1 — pass --expose to bind all interfaces, or front it with tailscale serve for HTTPS). Even read-only, a viewer sees the selected pane's full scrollback, so don't serve panes showing secrets. Access is gated by a fresh random token minted on each start (the daemon's own control token never touches the network; API calls authenticate with a Bearer header rather than a query string, except the SSE output stream, which must carry the token as a query parameter because EventSource cannot set headers), and nothing listens until you run the command. The page is installable: iOS "Add to Home Screen" works over plain HTTP, and full PWA install (Android) plus offline app-shell caching work behind HTTPS. Options: --port (default 7681), --expose, --host <addr>, --allow-input, --status, --stop.
- wmux web is now usable from a phone, not just viewable — and it starts from the titlebar. The browser surface gained the things a touch device actually needs. A key bar puts the keys a phone keyboard cannot produce one tap away (Esc, Tab, Ctrl, Alt, arrows, | / ~ - _, Home/End/PgUp/PgDn); tap a modifier to arm it for the next key, double-tap to lock it. A second row carries the keystrokes you actually need when an agent is waiting on you — Shift+Tab, Ctrl+C, yes, continue, /compact, /clear, /resume. Text size is adjustable, with two view modes: fit-the-whole-width for a glance, or 1:1 with sideways scroll when you need to read (previously the pane was always squeezed to the viewport, which on a phone meant unreadable). Notifications arrive in the page: when a pane asks for approval of a sensitive action, or emits a desktop notification, a banner appears — even while you are watching a different pane — and tapping it jumps there. A fleet strip shows every pane's status at a glance, with an attention dot on panes that called for you. Pairing no longer means typing a 36-character token on a phone keyboard: the server prints a 6-character code (/pair, valid 10 minutes, single use, 5 attempts) that the phone exchanges for the token. And the whole thing can be started without a terminal — a quiet web control in the titlebar opens a popover with Allow-input / Expose-to-network opt-ins, the scrollback warning, and one Start button; while running it shows the bind address, viewer count, a copyable URL, and the pairing code in large type. Read-only remains the default and is enforced server-side at the pty.write boundary, so a read-only server refuses input even if the page is tampered with.
- A "welcome home" briefing when you open a workspace. The Command Deck now greets you at the top of the orchestrator thread with a one-shot, deterministic summary of what the judgment engine already knows: what changed while you were away ("2 finished, 1 now blocked on you"), what is blocked on your decision, how the fleet stands right now ("1 needs you, 2 running"), and — the "look at this first" answer — the single pane most worth your attention, named and one click from its terminal. It deliberately doesn't repeat the Fleet roster sitting directly above it. It is a pure read of existing state: no brain turn is spent, nothing is throttled, and it |
| 3.32.0 | 23 de juliol del 2026 | — | 64 bits EXE Notes de la versióAdded
- Per-pane agent memory, live in Fleet View. Each pane's card now shows the resident memory of the agent process running in it (the CLI plus any child it spawned), attributed from the process tree and refreshed on the existing Fleet-View liveness batch — no extra polling while the panel is closed. Makes it obvious at a glance which session is the heavy one when the machine gets tight.
- Groundwork for installing the per-account usage statusline from within the app. The statusline setup logic (wmux setup-statusline) is now exposed to the renderer through IPC handlers (statusline:bridge:status / statusline:bridge:install), mirroring the hooks bridge pattern, so an upcoming Settings UI can let an app-only user (winget/Setup.exe) who never opens a terminal discover and enable it. No user-facing UI ships yet with this change. Same explicit user-click constraint as hooks: never auto-run at boot. (#555)
- The orchestrator now resolves questions it already knows the answer to, instead of freezing on them. In auto mode the Command Deck brain previously escalated every fork to a human decision and halted its loop — even when an operator rule it had already quoted answered the question (the real incident: it recommended the correct option, cited the rule, and still froze for a day). Three changes restore actual judgment. First, the brain's turn context now states its decision authority per mode: an auto workspace is explicitly told to resolve forks from standing rules and escalate only genuine residuals, while assist stays report-and-recommend and off gets no ambient instructions at all — previously all three modes received byte-identical guidance. Second, a new operator-editable deck-policy.md (seeded on first run in the wmux data dir) carries binding standing rules the brain may act on directly — unlike orchestrator memory, which deliberately remains non-executable background context; policy rules still can't grant tools or override safety, and risky/irreversible actions still require a human. Third, the escalation prompt itself now demands a resolve-first check (policy → conventions → memory) before raising a decision, and when the operator's answer corrects the brain's judgment, it persists that correction to memory so the same class of question isn't raised again.
- A decision left unanswered no longer blocks the orchestrator forever. A brain-raised decision used to freeze the workspace's autonomous loop indefinitely until a human clicked resolve. Pending decisions now have a TTL (default 30 minutes, configurable): once it elapses, the next heartbeat wakes the brain for a re-examine turn — re-state the question with better context, or, in auto mode only, resolve it itself via the new deck_resolve_decision tool by citing the standing rule that settles it, then proceed. The self-resolve path is server-enforced (auto mode + TTL actually elapsed + a substance floor on the resolution text — all three checked in the daemon-side RPC, not just the tool description; the citing of the rule is demanded by the prompt, while the server guarantees the resolution isn't a bare token), re-examines are debounced to once per TTL window, a decision whose timestamp was lost can never be self-resolved (human-only), the brain may replace its own stale question with a sharper one (a fresh pending decision still refuses a second raise), and ordinary wakes remain blocked while a decision is pending, exactly as before.
- The orchestrator now runs a periodic level review, and caps how many brain turns run at once. Two additions harden autonomous (Command Deck) orchestration. A level-review heartbeat re-reads each armed workspace's current per-pane state every few minutes and, if a pane needs attention that no live event ever surfaced (a dropped hook, an event lost during a busy stretch), wakes the brain to catch it — routed through the exact same mode/decision/budget/rate gates as an ordinary event wake, so it can never wake more than the live path would |
| 3.31.0 | 22 de juliol del 2026 | — | 64 bits EXE Notes de la versióAdded
- Per-account Claude usage in Claude Code's statusline (wmux setup-statusline). The global StatusBar widget shows one account's 5h/7d usage, but panes in a single workspace can run different Claude accounts — each pane needs its own number. A new wmux setup-statusline command sets Claude Code's statusLine to a wmux script that renders model · account · 5h N% · 7d N% on the line under the input box; because the statusline process inherits CLAUDE_CONFIG_DIR from its own claude process, every pane shows the usage of the account it actually runs on — including accounts selected by hand with $env:CLAUDE_CONFIG_DIR. The numbers are zero-cost: Claude Code ≥2.1 pipes the session's live rate_limits (5h/7d used percentage) to the statusline on stdin, so there is no extra API traffic and no token spend — the script reads stdin plus wmux's accounts.json (for the account name) and nothing else. Installs into the default ~/.claude profile and every registered claude account; a user's own custom statusLine is never overwritten. --remove / --status supported.
Changed
- Statusline reset indicators are easier to read, and the 7d window now shows one too. The ↺ reset marker sat flush against the time (↺00:30) and double-width terminal fonts could swallow the first digit — there's now a space (↺ 00:30). The 7d window previously showed only the percentage; since "how long until it frees up" is exactly what you want to know when it runs high, it now shows the remaining time (7d 84% ↺ 52h, or ↺ 2d4h beyond 48h). Re-run wmux setup-statusline to update the installed script.
Fixed
- The per-pane "Resume" chip no longer appears while the agent session is still running. The chip (the ↩ affordance that reveals the conversation UUID and types the exact --resume command) is meant to surface only once the agent has exited — typing into a live Claude/Codex TUI would land in the agent's input box. On panes without OSC 133 shell integration, though, its only "is the agent busy?" signal was a decaying activity heuristic: an agent that stayed quiet for 2 minutes (a long thinking stretch, or a finished turn waiting for your reply) read as gone, and the chip popped up mid-session. The gate is now edge-triggered on process truth: when a hook or the live banner proves the agent is running, the daemon attributes the actual agent process in the pane's process tree (one snapshot per launch, then a ride on the existing liveness batch — no new polling) and reports alive/dead alongside the session. The chip stays hidden the whole time the process lives — however quiet — and appears exactly on its exit, whatever the exit path (double Ctrl+C, /exit, Ctrl+D, a crash). Shell-integration panes keep their existing authoritative OSC 133 gate; panes where no process could be attributed keep the old heuristic as a last resort.
- macOS zsh panes now percent-encode the directory they report, matching Windows. The zsh integration hook has reported the pane's working directory (OSC 7) since v3.30.0, but it sent the raw path while wmux's parser percent-decodes what it receives — so a directory whose real name contains a percent sequence (say build%20cache) was silently tracked as build cache, and a directory name containing a raw ESC or BEL byte could cut the report short and smuggle terminal escape sequences into the pane. The zsh hook now percent-encodes the path exactly like the PowerShell/bash hooks shipped in the previous fix — spaces, Unicode, literal % and control bytes all round-trip byte-exact — and the encoder shields itself from user rc options (a KSH_ARRAYS setopt from oh-my-zsh-style configs no longer corrupts the encoding). Shell integration scripts refresh automatically (v9) on the next daemon start. (#541 follow-up)
Added
- Both resume affordances gained a --dangerously-skip-permissions toggle (Claude only, on by default). The persistent Resume chip and the post-reboot recovery pill now each show a checkbox that forces --dangerously-skip-permissions onto the resume |
| 3.30.0 | 21 de juliol del 2026 | — | 64 bits EXE Notes de la versióAdded
- A browser pane's CDP target is registered as soon as the guest attaches, instead of only after the page finishes loading, so automation can reach a pane whose page is slow or unreachable. Two related fixes: an already-attached debugger no longer aborts registration outright (the guard never matched Electron's actual error text), which previously left a reloaded guest permanently unregistered. (#517)
- Discard hidden browsers (opt-in) — lightweight mode now has a memory lever. Lightweight mode only capped CPU; every hidden browser pane still held its full Chromium renderer in memory. A new sub-toggle under "Lightweight background browsers" ("Discard hidden browsers", default off) unloads a browser pane after it stays invisible for 5 minutes — the guest renderer process exits and its memory is reclaimed, and the pane shows a small "suspended" placeholder. Returning to the pane (or navigating it) reloads the page; scroll position and unsaved form input are lost, which is why it's opt-in and the dwell is generous. Panes playing audio are never discarded, and automation (MCP tools, screenshots) targeting a discarded pane wakes it automatically and waits for the reload before running — so background agent flows keep working. (#517)
- Lightweight mode for built-in browsers (opt-in). With many workspaces open, every embedded browser pane kept its Chromium renderer running full-speed even when its workspace was hidden — that CPU was burned on purpose so background automation (MCP screenshots, evaluate) never stalled. A new Settings → Terminal toggle ("Lightweight background browsers", default off) CPU-throttles a browser guest only while it is effectively invisible — hidden workspace, pane hidden behind another pane's zoom, unselected tab, or minimized window — and any automation touching a guest takes a short-lived lease that runs it full-speed for the duration, so background automation stays correct. (Classic background-tab timer throttling turned out to be inert for these guests — Electron keeps a CSS-hidden webview in the "visible" page state — so the throttle is applied as a CDP CPU-rate override, measured at a 2–5× CPU reduction on timer-driven pages.) This reclaims CPU only; renderer memory is unchanged. (#517)
What's Changed
- Lightweight mode for built-in browsers: CPU-throttle invisible guests (opt-in) by @openwong2kim in #528
- Discard long-hidden browser panes to reclaim memory by @openwong2kim in #530
- chore(release): 3.30.0 by @openwong2kim in #532
Full Changelog: v3.29.0...v3.30.0 |
| 3.29.0 | 21 de juliol del 2026 | — | 64 bits EXE Notes de la versióFixed
- Typing stays responsive — and Hangul/CJK composition no longer truncates — while an agent floods a visible pane. A TUI redraw is a burst of tiny cursor-move writes, and handing each one to the terminal separately made the GPU re-rasterize the whole grid dozens of times a second; while a frame was held for paint, keystrokes and IME composition events queued behind it, so fast typing dropped characters and "했습니다" could land as "했". wmux now honors the terminal's own frame markers (DEC mode 2026 synchronized output, which Claude Code and Codex emit): it holds a frame's intermediate writes out of the renderer and releases them in one shot when the frame closes, so the GPU paints once per redraw instead of once per fragment. A frame that opened right after a keystroke is treated as latency-sensitive and released within a frame or two, so your own echo always paints ahead of an agent's autonomous output. Windows ConPTY only for now.
- Switching workspaces no longer stutters when a hidden pane piled up a large scrollback. A pane that streamed output while hidden handed its whole backlog to the renderer in one parse on reveal, spiking the GPU across several frames. A large backlog from a daemon-backed pane is now re-synchronized from the daemon as a bounded screen snapshot instead of replayed in full, and a backlog that can't be re-synchronized is drained over frames rather than in one burst — so a switch stays smooth without ever dropping or losing output.
Added
- Notifications can be muted per category instead of all-or-nothing. Every notification now carries the kind of event that produced it — agent turn finished, subagent finished, awaiting approval, terminal (OSC 9/99/777), system/external — and Settings → Notifications has a switch per category. Before, the only knobs were global sound/toast/ring toggles, so quieting subagent chatter during parallel work also silenced the "awaiting approval" signal that actually needs you. Muted categories still land in the notification panel; only toast, sound, pane ring, and taskbar flash are suppressed, the same contract a muted workspace already had. Nothing is muted by default, and a notification whose source can't classify it is never suppressed by a category mute. The mute is honored even when wmux has no live window — the muted set is mirrored to the main process, so a category you turned off can't come back as a desktop banner while the app sits in the tray. Subagent-vs-main-agent classification comes from the Claude Code hook bridge; the text detector can only distinguish approval prompts from turn ends, and the Settings copy says so. (#516)
Fixed
- A single failing installer step no longer discards the platform's whole release. Forge builds makers in sequence and stops at the first failure, so when the macOS DMG step hit a transient hdiutil detach error during v3.28.1, the upload step never ran — and the runner was thrown away with a perfectly good .zip still on it. That zip is what backs the auto-update feed, so one flaky maker silently took out both the download and auto-update for macOS until the job was re-run. Both the macOS and Linux upload steps now run regardless of whether the build step failed, publishing whatever artifacts did get made.
- macOS: panes get the shell environment you actually have. zsh was started interactive but not as a login shell, and on macOS the standard PATH is assembled by /etc/zprofile — a login file that runs path_helper. So a pane inherited whatever PATH the app was launched with (launchd's minimal one for a GUI launch) and lost /opt/homebrew/bin, /usr/sbin, /sbin, /Library/Apple/usr/bin and every /etc/paths.d entry. .zshrc still ran, which is why the shell looked fine right up until an unqualified Homebrew command failed. Panes now start a login shell on macOS, matching Terminal.app, iTerm2 and VS Code. The .zprofile/.zlogin stubs that delegate to your real files already existed — they were simply never read. (#519, reported by u/DauntingP |
| 3.28.1 | 20 de juliol del 2026 | — | 64 bits EXE Notes de la versióFixed
- The Git tab (worktrees + review roster) now finds the repo an agent is working in, even when the shell it runs in sits elsewhere. Repo context used to come only from the pane's shell working directory — but for an agent pane (Claude / Codex TUI) that is typically the directory the shell was started in (often the home dir), while the agent works in a repo somewhere else. Result: the sidebar showed the branch just fine, yet the Git tab said "not a git repository". Repo resolution now falls back to the hook-reported agent directory (the same value the sidebar branch badge already trusts) when the shell's own directory doesn't resolve to a repo.
- Resume no longer silently downgrades to --continue when the pane's tracked directory is stale. The resume chip/pill only offers the exact --resume <uuid> form (with the recorded permission flag) when the conversation's origin directory matches the pane's live directory — but it compared against the shell's tracked cwd, which goes stale across cd X; claude one-liners (no prompt render in between, so the shell never reports the new directory). A legitimate exact resume was then downgraded to --continue, dropping the permission flag and possibly resuming a different conversation. The match now also accepts the hook-reported agent directory (the same value the sidebar branch badge trusts). Nothing auto-runs either way — the command is only typed, and you press Enter.
- A pane's tracked working directory can no longer be corrupted by terminal output that looks like a shell prompt. Two guards, observed live (a pane's directory stored as the literal token path, which then broke Git-tab repo resolution): once a shell has proven it runs the wmux integration hook (it emitted an OSC 7), prompt-scrape directory detection is permanently disabled for that session — the hook is authoritative, so scraping could only ever add false positives; and scraped values must now be absolute (or ~-anchored) paths on every platform — a bare relative token is never a real working directory.
- The orchestrator can tell a pane that finished from a pane that asked you something. A pane's turn-end reached the orchestrator as "pane stopped" and nothing else, so the only way to learn why it stopped was to read the rendered terminal — where a question the agent printed looks exactly like text sitting in its input box. Orchestrators mis-read that: reporting panes as "still running" while they sat blocked on an unanswered question, and pressing Enter to "submit" a line that was never there. A turn-end now carries the agent's own closing words, lifted from its transcript rather than the screen, and a stop that ends in a question (including Korean endings that carry no ?) is stamped BLOCKED ON A QUESTION with the question quoted — the same treatment reviewer comments already get. The pane's question is also published as pendingQuestion on pane_list, so an orchestrator can check whether a pane is waiting on it without reading the terminal at all. Deliberately not a new agent status: waiting already meant "turn ended", and what was missing was the content, not another state.
- terminal_send_key no longer implies it submitted something. Sending enter returned a bare success whether or not anything was committed, which is what let an orchestrator report a blocked pane as working. Enter presses now come back with an explicit note that delivery is not submission, and the tool description points callers at terminal_send({ text, submit: true }) for answering an agent that is waiting on them.
What's Changed
- fix(macos): sign and notarize the DMG container, not just the app by @openwong2kim in #510
- fix: resolve the agent's real repo when the shell sits elsewhere (Git tab, cwd guards, resume chip) by @openwong2kim in #511
- docs(readme): cover macOS support by @openwong2kim in #512
- fix(deck): tell the orchestrator when a pane is blocked on a question by @openwong2kim in #513
- chore(release): 3.28.1 by @openwong2kim in #514
|
| 3.28.0 | 20 de juliol del 2026 | — | 64 bits EXE Notes de la versióAdded
- Resume a pane's agent conversation right from the pane. After an agent (Claude / Codex) exits back to a shell, the pane header shows a quiet ↩ Resume <agent> chip whenever wmux captured that conversation's session. Clicking it reveals the conversation UUID (with a copy button) and a preview of the exact command it will type; Resume types claude --dangerously-skip-permissions --resume <id> into that pane — the recorded permission mode is restored, and the exact-session form is used only while the pane's directory still matches the origin (otherwise it falls back to --continue). Nothing auto-runs; you press Enter. The chip stays hidden while an agent is actually running in the pane: OSC 133 shell state is the authoritative gate (a foreground command owns the PTY), with an agent-activity heuristic as fallback when shell integration is off — so a resume command can never land in a live agent's input. Available on any agent pane anytime, not only right after a reboot.
- The daemon now keeps a durable log at ~/.wmux/daemon.log. The wmux daemon runs detached with its console output discarded, so a live daemon left no trace of what it did — which made post-reboot session-recovery failures impossible to diagnose. Every daemon line is now mirrored to a rotating file (5 MB + one backup), and the reboot-recovery pass logs how many sessions it loaded from state and how many it respawned (so "loaded 0" — a persistence failure — is distinguishable from "loaded N, respawned 0" — a spawn failure). The last-resort synchronous state save on OS shutdown, previously Windows-only, is now registered on macOS/Linux too as a clean-exit backstop.
- Safely "merge" a worktree into your local base from the Git tab. Each feature-worktree row gets a Merge button. It never touches your local main (or the repo's default branch): it performs a git-native merge in an isolated worktree branched off the base. When there are no conflicts it automatically runs a verify gate (npm test + npm run lint) and — only if it passes — shows a one-line summary ("N files changed · verify passed") with Land (fast-forward the base to the result) / Discard (roll back) buttons. On a conflict nothing is auto-resolved; a "Conflict — open with Claude" button opens that isolated worktree as a new workspace so you can resolve it yourself (with Claude). Pass/fail is judged solely by the real process exit code, never by "done" text, and the in-flight merge state is derived from git on disk, so Land/Discard survives an app restart.
- Git joins the right dock as a tab, plus a git signal line and a Git button in the sidebar. The right dock is now three tabs: Orchestrator · Git · Channels. The Git tab shows the current workspace's worktrees + PRs on top and a diff roster (the former Review, merged in from its own tab) below, in one scroll. The left sidebar footer gets a Git button below Agent (opens the dock straight to the Git tab; a badge shows how many workspaces have uncommitted changes), and each workspace name now carries a git signal line: alongside the branch, read state at a glance by color — green ● (clean) / amber ●N (uncommitted changes) / blue ↑N (ahead) / red ↓N (behind). The bottom diff roster (Review) now lists only workspaces in the same repo (including its worktrees) as the one you're looking at, matching the merge workflow's scope. Earlier layouts (top header tabs, full-screen center surface) were reverted.
- Agent toolbar: Broadcast is back and works. The old Broadcast prompt relied on a browser dialog that never existed in the packaged app; it now opens an inline popover that shows how many terminals it will hit, sends to every terminal pane in the current workspace, and reports how many succeeded or failed.
- macOS: the wmux CLI now installs itself from DMG/ZIP installs. On first launch the packaged app symlinks the bundled CLI to /usr/local/bin/wmux, falling back to ~/.local/bin/wmux (with a PATH hint) when permissions deny it. Homebrew-owned or any foreign fil |
| 3.27.0 | 18 de juliol del 2026 | — | 64 bits EXE Notes de la versióAdded
- A merge conflict on a pane's PR now wakes the owning workspace too. Completing the PR-feedback trio (red CI, review comments, and now conflicts): when a pane's pull request becomes conflicting against its base, the workspace's orchestrator wakes once — auto may send the pane one instruction to rebase/merge its base and resolve the conflict, assist reports, off stays silent. Edge-triggered per episode (fires once, re-arms when the conflict clears) and rides the same throttled gh read the review-comment router already makes, so it adds no extra polling. GitHub via gh's mergeable, GitLab via has_conflicts.
- New Review tab in the deck: every workspace's diff, one screen. The dock now has a Review tab listing every open workspace with its branch, PR badge, and uncommitted diff stat (files / +adds / −dels), dirty rows first — so when several agents work in parallel you can see at a glance who changed what and step into each review. The Diff action jumps to that workspace and opens the existing diff surface (hunk-level review/adopt unchanged); Go just switches. Pull-based (load on open + manual refresh), no polling.
- New PR review feedback now routes to the owning workspace too. When a reviewer leaves a comment (conversation, review verdict, or inline code comment) on a pane's pull request, the workspace's orchestrator wakes with the author and a snippet of the latest comment — under the same policy as the CI signal: auto may send the pane one instruction to address the feedback, assist reports, off stays silent. Watermarked per pane on comment timestamps, so checking out a branch with existing review history never wakes anyone; only strictly-new comments fire, once per batch. Rides the existing gh caches (30s PR-list TTL, updatedAt-keyed detail), throttled to one check per pane per minute.
- A workspace's orchestrator now wakes when its PR turns red, and can drive the fix. When a pane's pull-request CI checks flip from passing/pending to failing, wmux fires a one-shot signal that wakes the owning workspace's brain through the same event-push path as a stopped pane — so a broken build routes straight back to the agent that owns it instead of waiting for you to notice the red badge. It is edge-triggered (fires once per red transition, re-arms after the PR goes green again, never spams while it stays red) and inherits the workspace's autonomy policy exactly: auto may send the pane one instruction to investigate and fix the failing checks, assist surfaces it as a report, and off stays silent. The wake prompt carries the PR number and URL so the brain acts without a poll. Closes the "detect → route back to the responsible worker" loop that competing multi-agent orchestrators ship.
- Sidebar workspaces now show git sync state next to the branch name — ↑2 ↓1 ●3 for commits ahead/behind the upstream and uncommitted changed paths. A clean, synced checkout shows nothing (only trouble earns pixels), everything renders in the muted context color, and the tooltip spells the numbers out. Fed by one git --no-optional-locks status per repo per 15 s riding the existing metadata poll; a branch switch invalidates immediately.
- Sidebar workspaces now show how long they've been idle — a muted · 3m next to the name once a workspace has gone a minute without agent activity, counting up through minutes/hours/days. The status dot already said what a workspace is doing; this says how long it's been waiting for you, which is what matters when running several unattended agents. Hidden while an agent is running and until the first activity of the session. Plain terminal output also counts, not just agent activity: shell-only workspaces never tripped the agent activity gates (the daemon's byte-threshold 'running' detector needs a 2000-bytes/3s burst), so a pane you'd been using by hand used to read as idle-forever. Raw PTY output now stamps a separate per-surface clock (throttled to once per 30 s, kept apart from the agent-status derivation so a quiet |
| 3.26.0 | 17 de juliol del 2026 | — | 64 bits EXE Notes de la versióAdded
- Type /clear to the orchestrator to reset its context. The brain's conversation memory (and its persisted resume session) is dropped, so the next turn starts completely fresh — useful when it has accumulated stale instructions or gone down a wrong path. The visible transcript stays as your audit trail; /reset works as an alias. An in-flight turn is interrupted first.
- wmux now offers to install its Claude Code hooks — and tells you when you're missing them. Agent completion and approval detection is hook-primary, but the hook bridge previously required knowing the wmux setup-hooks CLI existed; without it, every signal silently degraded to screen-reading. A prompt now appears at launch when hooks are missing, and again when you raise a workspace's agent mode — with an Install button that does the same idempotent install as the CLI. wmux still never edits your Claude settings without that explicit click.
Changed
- The agent mode knob is now three honest positions — Off, Assist, Auto (danger) — and the default is Off. The previous four modes (off/manual/assist/orchestrate) collapsed into three that mean what they say: Off (the new default) gives the orchestrator no autonomy at all until you opt in; Assist wakes it only when a pane is blocked on input, to notify you — it never approves anything; Auto (danger) wakes it on every agent event and lets it drive work to completion on its own judgment, including pressing approval prompts. Existing workspaces keep working: a stored manual mode reads as Off, orchestrate as Auto.
- Auto mode actually presses approvals now. The orchestrator was told "regex-detected prompts are notify-only, never approve" while the only source of approval events was the regex detector — so even the most permissive mode never pressed anything, silently. In Auto mode the brain is now instructed to verify first (read the pane and confirm a real approval prompt is on screen) and then press it, so a stray "y/N" in ordinary output still can't trigger a blind keystroke. Assist mode remains notify-only.
- The orchestrator treats your pane roles as a workflow, not just labels. With Planner / Builder / Reviewer panes set up, non-trivial work now flows through them unprompted — plan first when the task is ambiguous, and review before reporting "done" — instead of one pane doing everything while the team you assembled sits idle.
- The orchestrator now reuses your existing panes before spawning new ones. Its standing instructions gained a reuse-before-spawn rule: check the pane list for an idle shell or a finished agent and send work there, spawning a fresh pane only when nothing is free or the work genuinely needs to run in parallel. Previously it happily split a new pane while a suitable one sat idle next to it.
Fixed
- Dropdown menus were white-on-white in dark themes. Native <select> popups (like the Fleet role dropdown) rendered their option list on the OS default white background while the text inherited the theme's light color. The popup now follows your theme in both directions.
What's Changed
- ci: stop the phantom PR failures — drop duplicate runs, unpin apt from a repo we don't use by @openwong2kim in #483
- docs(todos): the split-brain daemon fix shipped in #323, not on a stranded branch by @openwong2kim in #484
- Three-mode autonomy (off/assist/auto), approvals that actually press, hooks install prompt, /clear by @openwong2kim in #485
- chore(release): 3.26.0 by @openwong2kim in #486
Full Changelog: v3.25.0...v3.26.0 |
| 3.25.0 | 17 de juliol del 2026 | — | 64 bits EXE Notes de la versióAdded
- The notification panel now remembers where you were. Closing and reopening the bell panel restores the exact scroll position you left off at, instead of yanking you back to the top of the list mid-triage. If new notifications arrived while the panel was closed, it snaps to the top instead so the newest entries are immediately visible (the list is newest-first). The memory is per-session and in-memory only.
- Codex approval prompts now raise a "needs your input" alarm, mid-turn. When Codex CLI pauses to ask "Would you like to run the following command?" (or the edit-approval and first-boot directory-trust variants), wmux now detects it and fires an awaiting_input notification — previously a Codex pane waiting on approval sat silent until you happened to look, because Codex's own notify hook only fires when the whole turn completes and says nothing about mid-turn pauses. The prompt strings were transcribed from a live Codex CLI 0.145.0 session and are matched whole-line, so an agent merely talking about an approval prompt doesn't trigger a false alarm. Clicking the alarm jumps to the waiting pane, like every other notification.
- Connect a different brain to the Command Deck — Hermes Agent is the first non-Claude orchestrator. A new Settings → Orchestrator → Orchestrator brain picker chooses which agent runtime drives the deck: Claude Code (the default, unchanged) or Hermes Agent over ACP — the open Agent Client Protocol, so further ACP-speaking agents are a configuration entry away, not a new integration. The connected brain gets the same fleet hands (wmux tools over MCP), the same server-side guardrails (it cannot close panes or leave its workspace), streams into the same deck chat with tool-call chips, and keeps its own conversation history across restarts — each brain's thread is separate, and switching back resumes where that brain left off. wmux never touches the brain's model credentials: Hermes authenticates through its own setup on your machine, exactly like your Claude login. Requires the vendor's CLI installed; if it isn't, the first command tells you plainly instead of hanging.
- Orchestrator full-power mode (opt-in): your Claude Code skills, CLAUDE.md and hooks, inside brain turns. By default the Command Deck orchestrator runs "raw" — a fully explicit contract that deliberately loads nothing from your ~/.claude setup, because personal hooks firing inside every brain tool call cost real latency and can feed events back into wmux itself. A new toggle in Settings → Orchestrator opts a workspace's brain into the full Claude Code ecosystem: skills become invocable, your CLAUDE.md applies, and your hooks run. The brain's tool guardrails do not widen with it — it still cannot close panes, spawn subagents, run shell commands, or edit files, a skill's embedded inline-shell syntax is replaced with a placeholder instead of executing, and while the toggle is ON the brain also cannot write its memory notes (Write is hard-blocked in this mode so that no personal permission rule can widen it — a conservative first cut; relaxing that is a separate decision). One thing to understand before opting in: your hooks are your own code — they run inside brain turns outside any wmux sandbox, exactly as they do in your own Claude Code sessions. The toggle applies from the next brain turn on any path — typed, scheduled, or event-woken — the conversation carries over, and a restart restores it.
Changed
- The orchestrator's guardrails moved into wmux itself — groundwork for connecting non-Claude brains. Until now, "the orchestrator can't close panes or tear down workspaces" was enforced by options passed to the Claude SDK — a future non-Claude brain wouldn't have honored any of it. Three server-side layers now enforce the same contract for ANY brain runtime: the brain's tool catalog simply doesn't contain teardown tools (they're never registered, so no brain can call them), the pipe refuses teardown methods from a brain even if a future |
| 3.24.1 | 16 de juliol del 2026 | — | 64 bits EXE Notes de la versióFixed
- Typing no longer intermittently goes dead in a pane until you open a new one. On some machines, keystrokes would sporadically stop reaching the terminal — you'd type and nothing happened, and the only way back was to split off a fresh pane. The cause was a focus tug-of-war: when the pane that should hold keyboard focus was momentarily off-screen (mid workspace-switch or a re-mounting terminal), the focus self-heal kept shoving focus at it, focus bounced straight back to nothing, and the loop spun — dropping the keystrokes caught in between. The self-heal now refuses to hand focus to a terminal that isn't actually visible and confirms focus truly landed before counting it as recovered, which breaks the loop. It also now records which element dropped focus, so any remaining cases name their own cause in the logs. (This is a distinct bug from the earlier IME "claim-storm" — the field logs ruled that out.)
What's Changed
- fix(terminal): stop the focus self-heal from thrashing input dead by @openwong2kim in #468
- chore(release): 3.24.1 by @openwong2kim in #469
Full Changelog: v3.24.0...v3.24.1 |
| 3.24.0 | 16 de juliol del 2026 | — | 64 bits EXE Notes de la versióAdded
- You can turn off "start wmux when Windows starts." wmux registers itself to launch at login on install, but that was never optional — if you didn't want it running every boot, there was no switch. Settings → General now has a Startup toggle that flips it on or off live (it reads and writes the actual Windows startup entry, so it always reflects the real state). Turning it off sticks across app updates — an update no longer silently re-enables autostart behind your back. Windows only; the toggle is hidden on other platforms. (#460)
- The orchestrator can pause and ask you a decision — and it waits, even across a restart. When the orchestrator hits a fork it shouldn't settle on its own — an ambiguous requirement, a risky or irreversible step, a real choice between approaches — it can stop and put the question to you instead of guessing. Its working loop parks (it stops auto-advancing on agent events and scheduled ticks) and a "Decision needed" card appears in the Orchestrator thread, with your options or a free-text answer; the loop stays paused until you respond. The pending decision is saved to disk, so it survives closing and reopening wmux — come back later and the question is still waiting, and answering it resumes the orchestrator from exactly where it paused, with your answer handed to it. It's the orchestrator's own judgment to ask, not a new setting to configure.
- The orchestrator now tells you when it hits a Claude rate limit. When the orchestrator's own Claude session hits (or approaches) a subscription rate limit, an amber notice now appears in its conversation — naming the window (5-hour / 7-day), the account it's running on (if you've bound one), and roughly when the window resets. A hard limit reads "limit reached … new turns keep using this account until you switch"; approaching a limit is a quieter heads-up. It's read from a first-class signal the Claude SDK emits (not guessed from an error), attributed to the account the session actually launched on, and de-duplicated so a burst of retries doesn't spam the thread. This is the detection groundwork for account switching; the orchestrator doesn't switch accounts on its own yet.
- Settings → Accounts now shows live usage per Claude account. Each registered Claude account can display its 5-hour and 7-day quota utilization (e.g. 5h 42% · 7d 71%) right next to its login badge, turning amber as a window crosses 80%. The number is read the moment a Claude turn ends in a pane bound to that account — not by polling on a clock — so idle accounts cost nothing and the reading is always the freshest one. It shares the existing opt-in usage toggle (off by default, since each refresh spends one small request against that account's quota), and a per-row ↻ button forces an on-demand refresh whenever you want the current number. Windows and Linux only (macOS stores Claude credentials in a shared keychain that can't be read per account); Codex accounts show login status only.
- Every pane header now has quick action buttons. The pane tab strip gained a small right-aligned cluster of four icon buttons — split right, split down, new browser, and maximize/zoom — so the actions that were previously keyboard-only (Ctrl+D, Ctrl+Shift+D, Ctrl+B Z) are now discoverable with the mouse, right next to the tabs and the close button. Each button drives the same store action the keyboard already does (no new behavior), carries a tooltip with its shortcut, and stays pinned to the right while the tabs scroll on narrow panes. The maximize button (divider-separated at the end of the cluster) shows a pressed/restore state while the pane is zoomed; it replaces the old hover-revealed corner maximize control, which used to overlap the cluster. The cluster can be hidden in Settings → Appearance → Layout for a minimal, keyboard-only chrome (default on) — hiding it restores the corner maximize control. (There is no header button for adding a second terminal to the same pane — one pane holds one te |
| 3.23.0 | 14 de juliol del 2026 | — | 64 bits EXE Notes de la versióChanged
- Settings categories reorganized so General isn't a catch-all. The old General tab mixed language, terminal behavior, A2A, agent toolbar, MCP, updates, tutorial, and reset all in one place. Now: General keeps just language/updates/tutorial/reset; a new Terminal tab holds shell, startup directory, split cwd, IME guard, hidden-pane retention, and scrollback; a new Agents tab groups the orchestrator model/auto-wake, A2A execution, the agent toolbar, and MCP together (the orchestrator settings moved out of Claude integration, which now focuses on the plugin, usage meter, and accounts). First-run setup folded into About.
- Settings opens full-bleed instead of a small floating dialog. The Settings panel now fills the whole area under the titlebar — no dim scrim, no rounded floating card — so it reads as an app screen rather than a modal stacked on top of your terminals. Content stays centered at a readable width so full-width doesn't stretch every toggle description across the screen.
Added
- Manage multiple AI subscription accounts as first-class, and bind one per workspace. If you keep more than one Claude (or Codex) subscription — a work seat and a personal Max, say — you no longer hand-edit CLAUDE_CONFIG_DIR into a profile. Settings → Claude Integration → Accounts lets you add named accounts through a guided flow: it provisions an isolated config directory (your MCP servers, skills, and plugins are shared from your default account so you don't reinstall anything; only the login stays separate), hands you a one-line command to log in there, and registers the account automatically once login lands — wmux never sees or stores your token. Then right-click any workspace → Claude account / Codex account to bind an account to it: new terminals in that workspace launch on that account (a manually set CLAUDE_CONFIG_DIR in the workspace profile still wins). Binding applies to newly opened terminals; already-running ones keep the account they started with. Windows and Linux (macOS reads its credential from the keychain, which can't be partitioned per account).
- Give each agent a role, and the orchestrator routes work by it. Every agent in the Fleet roster (the orchestrator's Orchestrator tab) now has a small role dropdown — Builder, Reviewer, Tester, or Planner. Pick one and the orchestrator sees it in its workspace snapshot and prefers to send matching work to the matching pane (build work to a Builder, reviews to a Reviewer) instead of spawning a fresh pane for it. It is a preference, not a lock: an explicit instruction from you always wins, and the orchestrator falls back to any pane when none fits. Roles persist with the pane and are the operator's to set — the orchestrator reads them but never changes them. A role only matters on a pane that is actually running an agent; setting one on a plain shell is harmless and simply inert until an agent runs there.
What's Changed
- feat(orchestrator): operator-assigned pane roles the brain reads by @openwong2kim in #442
- Multi-account management for AI subscriptions (M0/M1) by @openwong2kim in #443
- Settings: full-bleed panel + tab reorganization by @openwong2kim in #444
- chore(release): v3.23.0 by @openwong2kim in #445
Full Changelog: v3.22.0...v3.23.0 |
| 2.9.1 | 17 de maig del 2026 | — | 64 bits EXE Notes de la versióWhat's Changed
- feat(keyboard): Ctrl+Tab cycles through panes (multi-view) by @openwong2kim in #37
- fix(paste): repair chronic partial-paste truncation across all input paths by @openwong2kim in #36
- feat(panes): cap workspace splits at 20 leaves with toast feedback by @openwong2kim in #38
- v2.9.1 — Daemon shutdown reliability + .txt active-hazard mitigation by @openwong2kim in #39
- substrate: SECURITY.md + filesystem hardening on daemon startup (Phase 3.2 baseline) by @openwong2kim in #41
- docs(protocol): M4 — workspaceId resolution paths + path-D limitation by @openwong2kim in #42
- fix: revert PR #41 filesystem hardening — ACL lockout regression in user dogfood by @openwong2kim in #43
- fix(main): capture daemonClient before before-quit race to avoid null deref by @openwong2kim in #44
- docs(internal): path-D call-site inventory for substrate Phase 2.1 by @openwong2kim in #46
- fix(daemon): #35 instrumentation, recovery PTY retry, before-quit timeout by @openwong2kim in #45
- fix(scrollback): three-layer Fix 0 — mount gate + race-free reconnect + restore toggle by @openwong2kim in #47
Full Changelog: v2.9.0...v2.9.1 |
| 2.9.0 | 14 de maig del 2026 | — | 64 bits EXE Notes de la versióWhat's Changed
- wmux Substrate 3.0 — Phase 0 + M0 (v2.9.0 ship unit) by @openwong2kim in #34
- feat(scrollback): v2.8.x → v2.9.0 chopped-dump recovery tool by @openwong2kim in #35
Full Changelog: v2.8.4...v2.9.0 |
| 2.8.4 | 12 de maig del 2026 | — | 64 bits EXE Notes de la versióWhat's Changed
- fix: restore workspace drag reorder by @dev-minggyu in #28
- fix(multiview): sticky group across navigation + MiniSidebar feature parity by @openwong2kim in #29
- fix(notifications): restore agent task-complete notification pipeline by @openwong2kim in #30
New Contributors
- @dev-minggyu made their first contribution in #28
Full Changelog: v2.8.3...v2.8.4 |
| 2.8.3 | 11 de maig del 2026 | — | 64 bits EXE Notes de la versiówmux 빌드 산출물에 부족했던 attribution 의무를 정리한 patch. THIRD_PARTY_NOTICES 가 Playwright 하나만 적혀 있었지만 실제 runtime 번들은 110 packages (16 직접 deps + Electron + ~93 transitive) 를 포함하고 있었다. MIT/ISC/BSD/Apache-2.0 의 "all copies or substantial portions" 조항을 모두 충족하도록 재구성. 코드 동작 변경 없음.
What's new
📜 라이선스 attribution 모두 충족
- THIRD_PARTY_NOTICES — Playwright 1 개 → 110 packages 로 채움.
- 분포: 98 MIT, 7 ISC, 2 Apache-2.0 (electron-squirrel-startup, playwright-core), 2 BSD-3-Clause, 1 BSD-2-Clause
- Zero copyleft. Zero unknown. 재배포 권리 위험 0.
- wmux 자체 LICENSE — forge.config.ts 의 extraResource 에 ./LICENSE 추가. 빌드 후 <install>/resources/LICENSE 에 위치하여 MIT 본문도 exe distribution 과 함께 carry.
- Electron 본체 LICENSE (Chromium / V8 / Node 커버) — electron-packager 가 install root 의 wmux.exe 옆에 자동 emit. 이미 충족.
🛠 자동 생성 스크립트 npm run notices
scripts/generate-notices.mjs — production deps tree 를 walk 해서 THIRD_PARTY_NOTICES 를 재생성한다. 외부 의존성 0 개 (npm ls --prod --all --json + node:fs 만 사용). 추가 install 없이 CI 에서도 그대로 실행 가능. dependency 변경 시 즉시 갱신.
🖱 Tray 메뉴에서 라이선스 진입점 3 개 신설
그동안 wmux 는 application menu 자체가 없어서 사용자가 라이선스 파일에 도달할 경로가 0 이었다. 이번 패치로 tray 우클릭 → 다음 항목 추가:
- About wmux — 네이티브 About 패널 (버전 / MIT copyright pointer / project URL)
- License (wmux) — wmux 의 MIT 본문 직접 열기
- Third-party licenses — THIRD_PARTY_NOTICES 직접 열기
shell.openPath 로 OS 기본 텍스트 앱에서 열고, 연결된 앱 없으면 showItemInFolder fallback.
Migration
자동. 사용자 액션 불필요. 외부 MCP 통합 측에 변경 없음. 빌드 자체에 영향 없는 데이터 + UI 보조 작업.
Why now
v2.8.2 까지의 빠른 hotfix 시리즈가 안정화되면서, 그동안 누락돼 있던 attribution 의무를 정리할 적기가 됐다. 단일 주제 patch — 다른 fix 와 묶지 않음.
🤖 Generated with Claude Code
Full Changelog: v2.8.2...v2.8.3
What's Changed
- chore(licenses): bundle LICENSE + regenerate THIRD_PARTY_NOTICES (110 deps) by @openwong2kim in #27
Full Changelog: v2.8.2...v2.8.3 |
| 2.8.2 | 10 de maig del 2026 | — | 64 bits EXE Notes de la versió@alphabeen 이 v2.8.1 출시 직후 PR #25 로 보고한 두 문제를 한 patch 에 묶는다. v2.8.1 의 startup brick 픽스 이후에도 runtime accumulation 시나리오 (X close 후 daemon 이 유지하는 detached 세션이 며칠에 걸쳐 누적) 에서는 hard cap 50 에 다시 도달했고, 더 나쁜 건 cap throw 가 renderer 의 Ctrl+T 핸들러에서 silent 하게 묻혀 단축키가 무반응처럼 보이던 결함이다. v2.8.1 사용자는 즉시 업그레이드 권장.
What's fixed
🟡 데몬 세션 hard cap 50 → 200 상향 (#25, by @alphabeen)
v2.8.0 의 세션 영속화 이후 cap 의 의미가 "한 세션 동안 최대 동시 PTY" → "lifetime 누적 detached PTY 총합" 으로 바뀐 결과, multi-workspace + 빈번한 split 사용자는 며칠 내 50 에 재도달. 50 자체는 commit 989dd8a 의 보안 하드닝 단계에서 정한 DoS 휴리스틱이었고 200 도 같은 카테고리 안 (둘 다 fork bomb 막기엔 헐겁고 일반 사용자 PTY 메모리 한계 안).
- soft cap 40 (recovery) / 7-day suspended TTL 정책은 무변경
- 헤드룸 10 → 160
- 근본 해결 (orphan detached GC) 은 v2.9 트랙으로 별도 검토
🔴 `pty.create` rejection 이 묻혀 단축키 무반응처럼 보이던 회귀
@alphabeen 이 PR #25 description 에서 짚어준 두 번째 문제. cap 도달 시 daemon 이 actionable 에러 (`Cannot create new terminal: 200 active sessions already running. Close some panes (or restart wmux) and try again.`) 를 throw 하는데 renderer 의 세 호출 지점 — `useKeyboard` Ctrl+T 핸들러, `AppLayout` empty-leaf 자동 PTY, `FloatingPane` 첫 열림 — 모두 `.then()` 만 달고 `.catch()` 누락 (또는 silent catch) 이라 rejection 이 묻히고 단축키가 무반응처럼 보였다. v2.8.1 Bug 1 의 actionable error 의도가 무력화되던 결함.
- 신규 IPC 에러 코드 RESOURCE_EXHAUSTED — wrapHandler.classifyError 가 cap 메시지 패턴 (cannot create new terminal + active sessions already running) 을 감지해 분류, 메시지에 [RESOURCE_EXHAUSTED] prefix stamp.
- useIpc 매핑 — DEFAULT_MESSAGES['RESOURCE_EXHAUSTED'] = "터미널 세션 한도에 도달했습니다. 일부 pane을 닫거나 wmux를 재시작한 뒤 다시 시도해주세요.", level 'warn'.
- 세 호출 지점 모두 ipcInvoke wrap 으로 통일 — result.ok 분기 + 실패 시 toast 자동 게재.
- Electron invoke envelope wrap 처리 — /codex review P2: ipcRenderer.invoke 가 main side 에러를 renderer 로 전달할 때 메시지를 Error invoking remote method 'X': Error: <orig> 형태로 감싸서 MESSAGE_CODE_PREFIX 가 `^` anchor 인 한 stamp 가 envelope 뒤로 밀려 매칭 실패 → 모든 coded error 가 다시 UNKNOWN 으로 떨어지던 path 차단. renderer regex 만 anchor 제거 (main side 는 자기 raw output 매칭이라 anchor 유지). 회귀 테스트 추가.
Migration
자동. 클라이언트 / 외부 MCP 통합 측에 변경 없음. 신규 RESOURCE_EXHAUSTED 코드는 내부 IPC 경계 안쪽 (renderer ↔ main) 에서만 사용.
Reviews & Tests
- @alphabeen PR #25 (외부 컨트리뷰터의 첫 PR — 정확한 진단 + 깔끔한 변경)
- /codex review — P2 (Electron envelope path) 잡힘. 같은 patch 에 fold-in
- 934 tests passing (+5 vs v2.8.1)
- typecheck + daemon (158.4kb) + mcp build 모두 clean
🤖 Generated with Claude Code
Full Changelog: v2.8.1...v2.8.2
What's Changed
- fix(daemon): raise MAX_SESSIONS 50 → 200 by @alphabeen in #25
- fix(v2.8.2): RESOURCE_EXHAUSTED toast + Electron envelope match by @openwong2kim in #26
New Contributors
- @alphabeen made their first contribution in #25
Full Changelog: v2.8.1...v2.8.2 |
| 2.8.1 | 10 de maig del 2026 | — | 64 bits EXE Notes de la versió@alphabeen 이 v2.8.0 출시 직후 보고한 세 가지 회귀 — 시간이 갈수록 wmux 가 사용 불가 상태로 빠지던 critical, recovered pane 출력이 깨지던 high, 매 시작마다 generic 에러 토스트가 뜨던 medium — 을 한 릴리스에 묶어 수정한다. v2.8.0 사용자는 즉시 업그레이드 권장 — 자동 마이그레이션이 누적된 sessions.json 을 첫 실행 시 정리한다.
What's fixed
🧨 Critical: 세션 누적으로 인한 brick 상태
v2.8.0 의 세션 영속화가 (1) 복구 횟수 상한이 없고 (2) 비명시 종료 세션이 영원히 남아 4–5 회 재시작이면 MAX_SESSIONS=50 소진. UI 에서 Ctrl+T 도 안 먹히고 generic "알 수 없는 오류" 토스트 도배 → 자가복구 불가능 상태에 빠지던 문제.
- Suspended 7-day TTL: 7 일 이상 inactive 한 suspended 도 prune. v2.8.0 의 누적된 sessions.json 도 첫 v2.8.1 실행 시 자동 정리.
- Recovery soft cap 40: 복구 후보를 lastActivity 내림차순 상위 40 개만 PTY 재생성. hard cap 50 에 도달해도 항상 신규 pane 헤드룸 10 슬롯 보장.
- Actionable error message: cap 도달 시 generic "알 수 없는 오류" 대신 Cannot create new terminal: 50 active sessions already running. Close some panes (or restart wmux) and try again..
⚠️ High: 복구된 pane 출력 interleave
저장 시점 PTY cols/rows 와 새 renderer geometry 가 어긋나 같은 줄에 두 paint 의 문자가 interleave 되던 문제 (예: Accessing workspace: → Accessingwworkspace:).
- Deferred output mode: recovery 경로의 createSession 이 deferOutput: true 로 시작 → bridge muted → 첫 resize 후 100 ms unmute. ConPTY 가 옛 geometry 에서 큐잉했던 출력은 drain & 폐기.
- 저장된 scrollback 은 ring buffer 직접 pre-fill 이라 보존됨.
🟡 Medium: 시작 시 generic 에러 토스트 폭주
main 의 daemon connect 가 비동기로 도는 동안 renderer 가 IPC 호출 → handler swap 무등록 윈도우에 떨어진 호출이 No handler registered 로 실패 → "알 수 없는 오류가 발생했습니다." 토스트 5–10 회 도배.
- main 이 단일 IPC handler daemon:get-ready-state 를 swap cycle 바깥에 등록.
- preload 의 daemon.whenReady() 가 ipcRenderer.invoke 사용 — renderer reload (crash recovery) 이후에도 정상 응답 (codex P2 fix).
- AppLayout 첫 reconcile 이 daemon.whenReady() await 후 pty.list / pty.reconnect.
Additional stability fixes
같은 hotfix branch 에서 발견·수정한 추가 4 건:
- Split 후 빈 pane placeholder 영구 잔존 — AppLayout auto-PTY effect 의 deps 가 activeWorkspace.id 만이라 split 으로 추가된 새 leaf 가 trigger 안 됐던 문제.
- 한글 IME 상태에서 Ctrl+D / Ctrl+Shift+D 미작동 — Hangul 레이아웃의 e.key === 'ㅇ' / 'Process' 미스매치. 두 곳에 e.code === 'KeyD' 폴백 추가.
- 분할 pane 키보드/마우스로 못 닫음 — Ctrl+W cascade + SurfaceTabs strip 무조건 렌더 + Ctrl+Shift+Q 추가 + i18n 4 locale 라벨 정리.
- Reconnect 후 출력 두 줄 중복 — pty.handler 의 daemonClient.on('session:data', ...) listener 누적 → per-session listener map 으로 분리.
Migration
자동. 첫 v2.8.1 실행 시 StateWriter.load 가 7 일 이상 묵힌 suspended 세션을 prune. 추가 액션 불필요. v2.8.0 에서 이미 brick 된 사용자도 업그레이드 후 정상 복구 (alphabeen 가이드 수동 파일 삭제 절차 더 이상 필요 없음).
외부 MCP 통합 측에 변경 없음 — 모든 변경은 daemon 내부 + main↔renderer IPC 가드.
Reviews & Tests
- /plan-eng-review CLEAR (4 architecture decisions resolved)
- /codex review caught one P2 (event-based whenReady deadlocks on renderer reload). Fixed via invoke-style query.
- 929 tests passing (+18 vs v2.8.0)
- Bug 1 dynamic-verified via bundled-daemon subprocess (50-session brick scenario reproduced & resolved)
- Bug 2/3 GUI-verified via CDP probe + visual observation
Closes #22.
🤖 Generated with Claude Code — team mode
Full Changelog: v2.8.0...v2.8.1
What's Changed
- fix(v2.8.1): session recovery hotfix (closes #22) by @openwong2kim in #24
Full Changelog: v2.8.0...v2.8.1 |
| 2.8.0 | 9 de maig del 2026 | — | 64 bits EXE Notes de la versióExternal AI 도구 (Claude Code, third-party MCP) 가 wmux 위에 워크플로우를 빌드할 수 있도록 세 개 신규 surface 동시 도입한 minor 릴리스. @alphabeen 의 RFC #15 가 직접 트리거.
What's in
🧩 Pane Metadata API (#16)
PaneLeaf 에 optional {label, role, status, custom} 부착. 외부 MCP 가 pane 별로 워크플로우 상태 (예: "Backend (running-tests)") 를 적을 수 있음. 두 도구가 같은 custom 키를 따로 쓰면 deep-merge 로 충돌 회피.
- RPC: pane.setMetadata / getMetadata / clearMetadata
- MCP: pane_set_metadata, pane_get_metadata
- 8 KB 직렬화 캡, label ≤ 64, role ≤ 64, status ≤ 128, custom ≤ 32 entries
🔔 JSON-RPC Event Bus (#21, originally #17)
1024-event ring + cursor-based polling. 외부 도구가 pane 생성 / 종료 / 포커스 변경, process 시작 / 종료, metadata 변경, workspace 상태 변경을 자율 구독 가능.
- RPC: events.poll(cursor, types?, max?)
- MCP: wmux_events_poll
- bootId 로 데몬 재시작 시 클라이언트 캐시 깨끗 무효화
- pane.list envelope 변경 → {asOfSeq, bootId, panes} (resync 후 reconcile 명확)
🔍 Cross-Pane Search (#20) — wmux 첫 cross-pane primitive
Ctrl+F → "All Panes" 토글 → 모든 live pane 한 번에 grep. 결과 ≤ 10 dropdown, > 10 progressive panel 자동 확장 (hysteresis + sticky bit). 클릭 → 해당 pane focus + scroll-to-line. regex 모드 + 잘못된 패턴 visual error.
- RPC: pane.search
- MCP: wmux_search_panes — AI 에이전트가 "JWT 에러 단 pane" 같은 자율 추론 가능
- 200-result cap, 20k lines/pane scan cap, 500-char line truncation
- v1 = 현재 워크스페이스만 (cross-ws v2 deferred)
🩹 Clipboard Fix (#19) — v2.7.4 잔존 버그
v2.7.4 의 selection-preserving fit 가드가 isVisible useEffect + document.fonts.ready 두 곳에 누락. PR #19 가 두 가드 추가 + selection 자동 복사 (150 ms debounce, main-IPC 경유로 size cap·lock retry·error toast 보존).
Security
- Cross-workspace 누출 차단: pane.search / pane.setMetadata 핸들러가 caller workspaceId 우선 사용. 외부 MCP 가 자기 ws 만 검색·작성. v2.7.2 mcp.claimWorkspace fix 와 동일 클래스 패턴.
Migration Notes
- 외부 MCP 통합 코드: 신규 surface 감지는 system.capabilities().features.{paneMetadata, events} 키로.
- pane.list 호출자: 응답이 envelope {asOfSeq, bootId, panes} 로 변경. result.panes[0] 으로 인덱싱.
- 이벤트 폴링 클라이언트: 매 응답의 bootId 비교, 변경 시 cached pane id / pty id / cursor 모두 폐기 + pane.list 로 reconcile.
- 데이터 마이그레이션 없음. 모든 신규 필드 optional.
Tests
911 passing across 79 test files (이전 baseline 776 → +135). tsc + MCP build clean.
v2 deferred
Cross-workspace search/metadata, push/SSE event delivery, dead-session scrollback dump 검색, optimistic concurrency (expectedVersion) on meta.set. 트래킹 #18 .
Stats
- 4 PRs merged today (#16, #19, #20, #21)
- 14 commits beyond v2.7.4 baseline
- ~3,800 lines added across feature code + tests + i18n
- 1 fixed: terminal clipboard intermittent failure
🤖 Generated with Claude Code — team mode
What's Changed
- fix(terminal): close remaining clipboard-copy gaps after v2.7.4 by @openwong2kim in #19
- feat(pane): optional pane metadata API for external tooling (PR 1/2) by @openwong2kim in #16
- feat(events): cursor-based JSON-RPC event bus (resubmit after #16 merged) by @openwong2kim in #21
- feat(search): cross-pane search with progressive disclosure UI + MCP tool by @openwong2kim in #20
Full Changelog: v2.7.4...v2.8.0 |
| 2.7.4 | 6 de maig del 2026 | — | 64 bits EXE Notes de la versióTerminal stability fixes (4-bug roundup)
#1 Hang on large output (CPU/RAM full blast)
- PTYBridge onData hot path: 8ms micro-batch accumulator (was unbatched, 5 sync middlewares per chunk)
- OscParser: char-by-char string concat → slice-based segment extraction (O(n²) → O(n))
- ActivityMonitor: 100ms timestamp guard on clearTimeout/setTimeout reschedule storms
#2 Ctrl+V paste partial drop
- useTerminal Ctrl+V / Ctrl+Shift+V handlers now use 4096-byte chunking (was a single write that hit the 100KB main-side backstop)
- pty.handler adds console.warn when the 100KB backstop fires (was silent drop)
#3 Copy completely broken
- clipboard.handler silent returns → typed throw (CLIPBOARD_INVALID_TYPE, CLIPBOARD_TOO_LARGE, CLIPBOARD_WRITE_FAILED) — surfaces Win32 clipboard lock contention (KeePass / RDP / browser tabs)
- 4 call sites (useTerminal ×3 + Terminal.tsx) await + try/catch, selection preserved on failure
- New showCopyErrorToast (i18n: en/ko/ja/zh)
#4 Multi-line selection: only last paragraph copied
- hasSelection() guard on ResizeObserver fit() and font/theme effects (xterm 6 SelectionService clears selection unconditionally on any rowsChanged)
- New Terminal option: windowsPty: { backend: 'conpty', buildNumber: 21376 } (xterm 6 ConPTY-aware reflow)
Refactor (DRY helpers)
- src/renderer/utils/clipboardChunk.ts — pastePtyChunked()
- src/renderer/utils/copyWithFeedback.ts — runCopyWithFeedback()
- src/renderer/utils/fitGuard.ts — shouldFitWhilePreservingSelection()
Tests
- 70 files / 776 passed (+49 new tests, 0 regressions)
- tsc + daemon-tsc clean
Full Changelog: v2.7.3...v2.7.4
What's Changed
- feat(cross-platform): batch 2A — icons, errors, shortcuts, boot-id Unix by @openwong2kim in #12
- feat(cross-platform): batch 2C — wmux mcp CLI + brew detector + macOS error wire-up + SMAppService research by @openwong2kim in #13
- Use detected shells for default terminal selection by @cloim in #10
- Fix PowerShell prompt OSC rendering by @cloim in #11
- feat(cross-platform): allow Unix shell basenames in PTY allowlist by @openwong2kim in #14
New Contributors
- @cloim made their first contribution in #10
Full Changelog: v2.7.3...v2.7.4 |
| 2.7.3 | 28 d’abril del 2026 | — | 64 bits EXE Notes de la versióFull Changelog: v2.7.2...v2.7.3 |
| 2.7.1 | 20 d’abril del 2026 | — | 64 bits EXE Notes de la versióWhat's Changed
- Add winget publishing step to release workflow by @openwong2kim in #5
Full Changelog: v2.7.0...v2.7.1
What's Changed
- Add winget publishing step to release workflow by @openwong2kim in #5
Full Changelog: v2.7.0...v2.7.1 |
| 2.7.0 | 19 d’abril del 2026 | — | 64 bits EXE |
| 2.6.0 | 17 d’abril del 2026 | — | 64 bits EXE |
| 2.5.0 | 15 d’abril del 2026 | — | 64 bits EXE |