what changed, and when

Changelog

All notable changes to swe-mux are recorded here.

The format follows Keep a Changelog, and the project follows Semantic Versioning. While the major version is 0, a minor bump may carry a breaking change; the entry says so explicitly when it does.

Entries describe what changed for someone running swe-mux, not how it was built. Internal refactors, test changes, and documentation edits are omitted unless they change observable behaviour, a supported platform, or a distributed artifact.

The release procedure that maintains this file is RELEASING.md.

Nothing yet.

0.1.5

2026-08-30 release notes
Added 7 entries
Changed 2 entries
Fixed 2 entries
all 11 entries
Added
  • swe-mux now ships an agent skill, embedded in every install. swemux --skill prints the copy matching the running release, and swemux install-skill writes it into the skill directories agent CLIs actually read - two writes inside a checkout cover every registered harness, with no third-party tool and no registry. The skill teaches an agent the in-session environment check and where the current contract lives (the mux MCP tools, or swemux --help); it deliberately enumerates no commands, so it cannot go stale between releases. Installing into the per-user skill roots, which reach every agent you run anywhere, prints the exact paths first and proceeds only under --yes; --remove takes back only files the installer can recognize as its own.
  • A PyPI install can now gain the tray, the native window, and shortcuts without reinstalling. Settings → General → Desktop integration installs or removes the Start Menu and Desktop shortcuts, and acquires the desktop shell's dependencies on one press - about 2.4 MB, verified against pinned hashes on the same path that fetches the speech libraries, never anything without an explicit press. One of those dependencies publishes no wheel at all, so the acquirer gained a pinned-sdist case with a strict rule: the archive is extracted, never built - nothing from it is ever executed, and an sdist that would need a build step is refused. The tray starts inside the desktop app, so after acquiring you launch (or restart) swe-mux once; every surface says so. On platforms with no desktop app the whole group is simply absent.
  • First run now asks how much swe-mux should do. Three experience tiers, phrased as three genuine products: pure terminal (real terminals, nothing watching - no hooks, no status detection, no fleet plumbing), deterministic (transcripts, live status, managed harnesses, the agent fleet surface; model-free), and automations (adds the scan timeline and the model-backed observers, under your budgets). A tier is a batch of defaults, never a lock: everything it turns off stays one switch away, the choice is re-applyable and reversible from Settings → General, and existing installs are never stamped with a choice they did not make.
  • The empty workspace now offers three first steps instead of nothing. A quest log on the empty stage points at the three setups that cannot finish in one screen: voice (opens the guided setup), isolated worktrees, and connecting a phone. It is capped at three by design - it will never become a todo list - the voice entry completes itself when voice is set up, and dismissing an entry is permanent, on every device.
  • Voice setup is now a guided walk. Settings → Voice gains "Guided setup" (also in the command palette and by voice: "set up voice"): pick the engine, watch the one-press download's three progress lines, test the microphone where a permission prompt is visible and explained, and hear one spoken sentence at the end. Every step drives the same controls Settings already has, so nothing new can drift.
  • The side panel's default density follows the chosen tier. A pure-terminal install opens with five panel tabs (Actions, Files, Notes, Git, Alerts) instead of ten; the agent-layer tabs stay one right-click away, exactly as before. Only a device that has never touched the panel visibility menu follows the tier default - any choice you have made, including showing everything, is never overwritten.
  • Agents can be handed the skill automatically, per harness. A new "Fleet access" control in Settings → Harnesses phrases the choice as capability - may agents in this harness's sessions see the fleet, and how do they learn they can - with MCP tools, the skill file, both, or neither. The two routes are deliberately not symmetric and the control says so: for Claude the skill travels as a session-scoped plugin from the mux data directory and nothing is written into your Projects, while for codex, pi, omp, and opencode it is written into the Project's .agents/skills/ at session start, because those CLIs read skills from nowhere else. Automatic delivery is off by default - swe-mux does not write into your checkout unasked - and turning it off later stops the writes without deleting anything.
Changed
  • A session row now reports the whole time that session has worked, not just the length of its current turn - the sum of every completed turn the record was willing to report, so a measurement it refused as "the last turn" is not quietly admitted into the total either. Context is also coloured on a finer ramp: the old one's first step arrived at 70%, by which point the decision it exists to inform - carry on in this thread or start a fresh one - has already been made for you.
  • The account switcher's quota figures line up. Each provider's rows now sit under one set of headed columns rather than being printed as a sentence per account, so several accounts can actually be compared against each other. The Git drawer's refresh also shows that it is reading rather than appearing to have finished.
Fixed
  • A transcript's Copy and Select controls no longer sit on top of the timestamp they were meant to clear. They were drawn at rest on every reply, sized against a gutter that predated the read-aloud markers. They now appear when asked for: on hover or keyboard focus with a pointer, and one at a time by tapping with a finger, which has no hover.
  • The daemon starts tens of seconds faster when its database has grown large. Every start used to re-verify the whole of mux.db before serving anything - a full-file read whose cost is the size of the file, measured at 60-84 seconds of every cold start against a 3.36 GB database, more than the entire rest of the startup sequence. The full verification now runs only when it can tell you something new: after the previous daemon died uncleanly (a crash or an external kill - the one signal that says the file's history is suspect), or when the last passing check is more than 24 hours old. Every other start runs a milliseconds header-and-schema probe instead, which still catches the gross-corruption class that used to stop the daemon coming up at all, and still quarantines a bad file before anything opens it. The trade, stated plainly: a corrupted page deep inside a cleanly-managed file can now go unnoticed for up to a day rather than until the next restart. Each start logs which check it ran and why, and deleting mux.db.last-verified.json beside the database forces a full check on the next start.

0.1.4

2026-08-30 release notes
Added 1 entry
Changed 1 entry
Fixed 2 entries
all 4 entries
Added
  • The Windows installer now installs swemux and mux, and puts them on your PATH. 0.1.3 added those names for people installing from PyPI and said plainly that the installer shipped no command-line program; it does now. The installer writes a third directory beside the app and the PTY supervisor, holding the two launchers and nothing else, and adds that one directory to your user PATH - no elevation prompt, because the whole install is per-user. Open a new terminal afterwards: Windows tells Explorer about the change, and a console that is already open never hears about it. It is a tickbox on the setup wizard, on by default, so a machine whose PATH you curate by hand can decline it; declining installs the commands anyway, and swemux doctor says where they are. Installing a newer version over the top leaves PATH exactly as it found it - one entry, never two - and uninstalling removes that entry and nothing near it, with a %USERPROFILE%\bin coming back as a variable rather than as whatever it meant at the time. swemuxd/muxd are deliberately not part of this: the application already is the daemon and starts one when you launch it.
Changed
  • Notes and Markdown files draw one more indent guide. The editor they share moved to Continuity 0.2.40, which draws a guide at the first indent level as well as the deeper ones. Indent guides are on by default in swe-mux, so this shows up on every nested list without anything to turn on; Settings → Text editor still turns guides off entirely if you would rather not have them. Nothing else about the editor changed.
Fixed
  • swemux doctor no longer reports three critical faults on a healthy install. Run from the new command-line client, the checks that ask whether the daemon can start were asking it of the wrong program - the client deliberately contains no daemon, no browser UI and no terminal backend, all of which live in the application beside it. Those rows now say so and point at where the daemon actually is.
  • Opening the Agent tab no longer stalls when a recorded directory is on a filesystem that is not reachable. Claude's ~/.claude.json keeps an entry for every directory it has ever run in, and finding the one for your session used to ask the filesystem about each of them in turn. A recorded directory can name anywhere you have ever worked - a drive that is no longer attached, a share on a machine that is off, a WSL distribution that is stopped - and Windows does not answer for those quickly, it retries. On one machine with 183 recorded directories, one of them a stopped WSL distribution, a single request took 367 seconds. Path comparison now settles the ordinary case from the directory names alone, and any question it does put to the filesystem is given a deadline and its failure remembered, so an unreachable location costs a moment once instead of a minute per entry. Sessions starting up were on the same path and were delayed the same way.

0.1.3

2026-08-29 release notes
Added 6 entries
Changed 3 entries
Fixed 4 entries
all 13 entries
Added
  • swe-mux now installs as swemux and swemuxd. The old mux and muxd are unchanged aliases of the same two programs, so nothing you have already written needs updating. The new names exist because mux is shared with an unrelated tool, and on a machine carrying both, whichever installed last is the one your shell finds. This applies to installs from PyPI; the Windows installer ships no command-line program yet, and an operator who wants one alongside it can uv tool install swe-mux.
  • A frontend fix can now reach an installed app without replacing it. mux ui-overlay packages the built frontend as a hash-verified overlay the daemon prefers over its bundled copy, at about 11 MiB against the ~370 MiB a full application update rewrites. The overlay is pinned twice - to the release and to a hash of the daemon's own route table - and an overlay that does not match the running backend is refused rather than served, because a frontend that disagrees with its daemon about which endpoints exist fails arbitrarily rather than legibly. Reverting to the bundled copy is one action.
  • Signing in to a provider account now starts from the account switcher. It could previously switch between saved accounts but not add one, so an install with nothing saved showed "No saved accounts" beside a manage... button - the one screen a new install always reaches, and the one with no way forward on it. A sign-in also outlives the request that began it.
  • An agent can name the model for a session it asks to spawn. Three of the five harnesses had declared model selection unmeasured; running their CLIs found all three accept a model flag, so this was being refused on a majority of harnesses because nobody had read --help. What the session actually started with is checked afterwards rather than assumed.
  • Agent authority can be set once for every Project. Fifteen Projects previously meant fifteen editors to say one thing, with no way at all to say it about a Project whose own file already held a value. An install-wide default now reaches unset fields and an install-wide ceiling caps every Project, and may only narrow.
  • Agent instruction files can be linked into a session's context and unlinked again.
Changed
  • The desktop application is about 111 MiB instead of about 400 MiB. The on-device speech closure - spaCy, CTranslate2, onnxruntime, misaki and their dependencies, roughly 277 MiB - is no longer shipped. Both speech features are off by default, so every install was previously downloading it, and letting the operating system scan it, for a capability it had not been asked to provide. It is now acquired on an explicit press, from pinned URLs verified against pinned SHA-256s, in one action that reports each part separately. A user who never enables voice saves about 289 MiB of download and disk; a user who does downloads about 193 MiB rather than 400 MiB.
  • An update now writes only the files that changed. Measured across two real consecutive builds, 97.9% of files and 92.3% of bytes were already present and are reused in place rather than rewritten - which matters twice, because a file that is not rewritten also keeps the verdict the operating system's scanner already gave it. A whole-archive checksum is still verified before anything is staged, and an update that cannot reuse enough falls back to replacing the application outright.
  • A Project can trust its own agents' edits to the verification gate. A branch that edited .worktree-verify refused its own land every time, and approving it was a per-digest act a human had to perform first - a routine edit here, so it stalled work on a review nobody was really performing. A gate edited by any other author still refuses and presents its bytes.
Fixed
  • Voice could refuse to start on a page that had been open a long time, and say the daemon was at fault. The voice status was fetched once when the page loaded, and a page that lost that one request never asked again - so every later attempt was refused with "daemon transcription is unavailable", a claim about a daemon it had never successfully reached and did not re-ask before refusing. The desktop application is what paid for this, because its page is opened once and kept for days across daemon restarts and updates, while a browser tab gets reloaded and quietly repairs itself. The status is now re-read whenever the event stream reconnects and again by the attempt itself before it refuses, and the reason is written where you can read it instead of appearing as a bare error.
  • The desktop application now decides its own microphone permission. It previously inherited whatever the installed WebView2 runtime happened to do with a request nobody answered, for whatever address the embedded browser had been pointed at, and remembered that answer in its profile. The microphone is now granted to swe-mux's own address, denied to any other, and nothing is persisted.
  • A land stopped by a verification block now restarts when the block is cleared. A refusal was terminal, so approving the gate's bytes fixed the next land and left the one that caused the block dead, to be asked for again by hand - or by an agent that had already been told its request was over.
  • An operator's own Land now shows the explanation the queue wrote for it. The queue composed a bounded message naming what stopped it, in which checkout, against which trunk, and what to do next, and then dropped it whenever the requester was a person rather than an agent.

0.1.2

2026-08-28 release notes

0.1.1 published to PyPI but produced no desktop artifact and no GitHub Release, so an installed copy was still told 0.1.0 was the newest version. This release carries everything 0.1.1 did, and the artifacts it could not build.

Added 2 entries
Fixed 2 entries
all 4 entries
Added
  • The Windows installer and the portable desktop archive, which 0.1.1 intended to publish and did not. See the 0.1.1 notes below for what they are.
  • The website's download section, filled from the release manifest rather than by hand, so it names the artifacts a release actually carries.
Fixed
  • The Windows installer did not build. Inno Setup resolves a relative source path against the installer script's own directory rather than against the working directory it is compiled from, so the build looked for the application bundle inside packaging/installer/ and found nothing. Every earlier step of the release had succeeded, which is why 0.1.1 reached PyPI without it.
  • The site now ships real screenshots, taken in a synthetic installation with invented projects and no personal data, rather than generated placeholders.

0.1.1

2026-08-28 release notes

A repair release. swe-mux[voice-local] could not be installed from PyPI at all in 0.1.0, and a configuration file carried between two hosts left the daemon unable to launch an agent.

This release also adds the first Windows installer, so swe-mux can be installed without Python.

Added 7 entries
Fixed 7 entries
Changed 2 entries
all 16 entries
Added
  • A Windows installer (swe-mux-0.1.1-windows-x64-setup.exe), attached to this release. It installs the application and its PTY supervisor, creates a Start Menu entry, and offers a desktop shortcut and a run-at-login task. It is not code signed, so Windows SmartScreen warns on first run; signing is planned. The portable archive is published alongside it for anyone who would rather not run an installer.
  • mux install-shortcut, which creates Start Menu and desktop shortcuts for an install that came from uv tool, pipx, or pip. No Python packaging mechanism can create a shortcut at install time, so this is the equivalent for those installs.
  • mux doctor now reports how swe-mux was installed, which directory its commands are in, and whether that directory is on PATH.
  • python -m swe_mux --where answers the same question with nothing but an interpreter, for the case where the commands are not reachable by name.
  • muxd prints a one-time hint at startup when its own commands are not on PATH, naming the directory and the command that fixes it.
  • A Help surface: a modal reachable from the command palette and by voice, from which the guided tour can be reopened.
  • Support for .tar.gz desktop bundles, which the updater already expected on macOS and Linux.
Fixed
  • pip install "swe-mux[voice-local]" failed for everyone. The published wheel required en-core-web-sm, which is on no package index, so both pip and uv refused the extra outright. The model is now acquired at first use and verified against a pinned hash, and the extra installs.
  • A config.toml written on one host and loaded on another kept values the new host cannot use. A file written on Windows and loaded on Linux launched claude.exe and codex.exe, so the Run menu could not start an agent while typing claude in a shell worked. In the other direction a POSIX worktree_root made the daemon refuse to load its own configuration. Ten settings are now re-derived when their stored value is shaped for a different host. A deliberate override the host can run, such as claude.cmd on Windows, is left alone.
  • A refused executable reported the wrong reason. Under WSL the Windows agent CLIs are reachable through interop, and swe-mux refuses them because such a session writes its transcript where no Linux path points and joins no Linux process group. That refusal reported "no such file or directory" rather than naming the binary it found and why it was rejected.
  • Provider login and harness launch failures now reach daemon.log, with the configured value and the resolution that failed.
  • The recovery that retries a configured codex.exe as codex ran only on Windows, where an .exe suffix is at least plausible, and not on POSIX, where it is certainly wrong.
  • cryptography and py-vapid are imported when the daemon starts and were not declared as dependencies; they arrived only by way of another package's requirements.
  • The desktop application opened a console window behind its native window. It is now a GUI entry point, and startup failures are reported in a dialog and written to desktop-shell.log rather than to a console that no longer exists.
Changed
  • The default theme is now Tokyo Night, and the default sidebar session row shows more at a glance. An existing installation keeps whatever it already had; neither default is applied to a configuration that has been written before.
  • The wheel no longer ships precompressed copies of the frontend bundle, which were duplicating content the wheel already compresses. They are regenerated once on first start, which takes under a second and makes the download about a third smaller.

0.1.0

2026-08-28 release notes

First public release.

swe-mux is a local daemon that owns long-lived pseudoterminals for coding-agent CLIs and shells, and presents them in a browser. Everything runs on the operator's own machine; the trust boundary is stated in SECURITY.md.

Windows is the proving platform and the only one with a frozen desktop application. Linux runs the daemon and the test suite from source. macOS is implemented and typechecked but has never been executed.

Added 52 entries · Session ownership and terminals · Projects and workspace · Agent sessions · Fleet control plane · Agent-facing MCP surface · Git · Voice and assistant · Remote access and desktop · Operations · Licensing and governance
all 52 entries
Added
Session ownership and terminals
  • muxd, an aiohttp daemon that owns every pseudoterminal, so closing or reloading the browser never stops a session.
  • A separate PTY supervisor process that holds the terminals, so live sessions survive a daemon restart, a backend reload, and a rebuild of the desktop application.
  • ConPTY on Windows and the stdlib pty module on POSIX behind one platform seam, with Win32 Job Object process ownership and its POSIX process-group equivalent.
  • Crash recovery for sessions the supervisor could not keep alive: a durable session registry, terminal checkpoints, and cold sessions that stay readable after their process ends.
  • Multi-device attach for one session, with exactly one connection permitted to write to the PTY and one arbitrated terminal size shared across devices.
  • Terminal-aware bracketed paste, copy/paste, find, clipboard capture, and a bounded clipboard-history ring that refuses secret-shaped copies.
Projects and workspace
  • Explicit Projects that bind sessions, layouts, notes, history, and file browsing to a canonical folder, plus optional Groups for sidebar organization.
  • A mixed-view workspace of panes, tabs, splits, and drag/drop, with desktop split geometry as durable Project state and a single-pane projection for mobile.
  • Project-owned notes, a file browser with editors, ignore rules, and leased non-recursive watches.
  • A reusable prompt library whose templates are inert text: selecting one inserts, and never submits.
  • Trusted task discovery and a per-Project Run menu over VS Code tasks, root package scripts, and .swe-mux/actions.toml; every task file stays inert until its exact current contents are reviewed and approved, and any edit revokes that approval.
  • Process and preview registration for Project-local listeners, with HTTP, WebSocket, and HMR traffic bridged through the daemon's own URL, and static document previews served from the checkout under a sandbox CSP.
Agent sessions
  • A harness registry with capability descriptors and adapter families, covering Claude Code, Codex CLI, and plain shells.
  • Automatic promotion of a nested agent started inside an ordinary terminal, through mux-local claude.cmd and codex.cmd shims that preserve the normal CLI invocation.
  • Session status detection with a durable transition ledger, a state watchdog, awaiting sub-reasons, and a golden detection corpus.
  • A fail-closed delivery-readiness contract (safe / blocked(reason) / unknown) that never authorizes automatic terminal input on unknown, and never reads child-agent completion as root-agent readiness.
  • Control-plane approvals driven by the harness's structured permission request rather than the terminal screen, with a floor that no configuration can reach past.
  • Managed provider accounts: save, relabel, reauthenticate, switch, and remove Claude and Codex logins, with subscription-window polling. Only authentication is copied, and switching is always an explicit act.
  • A read-only History browser that reconciles native Claude and Codex transcript directories at startup without moving or deleting the originals, and reads a Claude transcript as the branching DAG it is.
  • Launch profiles for shells and agents, and a WSL agent bridge with an explicit reachability probe.
Fleet control plane
  • Tier 0 deterministic fact capture with source pointers and fingerprints, scoped by a run boundary that survives an in-CLI conversation replacement.
  • Model-free detectors for loops and stalls, declared-versus-verified claims, documentation debt, and provenance.
  • A tree-sitter code-structure graph backing blast-radius, navigation, context, and test-gap reads.
  • An opt-in scan timeline with per-run grants, budgets, source rehydration, and dead-end extraction.
  • Attention ranking with an interrupt budget, four in-app delivery channels, breakpoint detection, and an absence digest.
  • Automation observers that can capture and report but cannot type, approve, spawn, execute scripts, or mutate a Project, governed by a per-Project enablement dependency graph and an install-wide ceiling.
  • An automation dashboard with policy, usage, and activity tabs as the single editor that may turn an automation off in either scope.
  • A prompt queue with head-of-line ordering, stranding, and seed staging for new sessions; gated auto-delivery with a stability window, quiet hours, an emergency pause, and a consecutive-send cap.
  • Agent-to-agent messages and a fleet queue, where a non-human sender's write ends at a human unless the receiver granted it or itself solicited it.
  • Scheduled runs (cron, interval, one-off) that go through the ordinary spawn, resume, and queue paths and grow no second authority.
  • A land queue that serializes branch landing: reconcile, then a verification gate whose exact bytes a human approved, then a fast-forward-only merge, returning conflicts and failures to the branch's own agent.
Agent-facing MCP surface
  • A per-session MCP server exposing reads over the fleet: sibling sessions and their status, paged transcripts, archived conversation search, Project notes, Agent Context sources, scan timeline and search, provenance, verified status, prior resolutions, and dead ends.
  • Bounded writes only: staging a message into another session's prompt queue, drafting a spawn request for human approval, arming a session-settle watch, and interrupting or ending a session behind a per-Project grant.
Git
  • Git status, comparison, diff review, first-time repository initialization, a commit graph, and a provenance ledger that separates who authored a change from who landed it.
  • Worktree creation and removal, including a background purge that never appears in git worktree list and never raises a checkout's dirty count.
Voice and assistant
  • Read aloud, from a summarized or verbatim slice of the last turn, through the OS voice engine, a local Kokoro model, or an explicitly acknowledged external Edge TTS provider that is never bundled.
  • Hands-free conversation: browser capture through an AudioWorklet, Silero VAD, a frame-counted endpoint gate, and faster-whisper transcription with configurable wake words and commands.
  • The Mux assistant, where the model proposes names, deterministic code resolves and executes through existing paths, and the confirmation floor for a consequential action is not configurable.
Remote access and desktop
  • A loopback listener plus an optional direct Tailscale listener carrying the same UI and API, with automatic Tailscale Serve on HTTPS 443 so a phone browser gets the secure context its microphone requires.
  • Web push notifications with per-device preferences, and device presence that decides which device the operator is at once for the whole application.
  • A Windows desktop shell: a WebView2 window, a system tray supervisor, login startup, and a frozen onedir bundle that can rebuild and redeploy itself while preserving live sessions.
  • A progressive web app manifest and service worker for phone installation.
  • A daily release check against a static version.json, which is the only request swe-mux makes on its own behalf: it carries nothing identifying the install, it downloads nothing, and update_check_enabled turns it off entirely.
  • An updater for the frozen desktop app (mux update --install <version>, POST /api/update/install) that downloads a release only on an explicit act naming a version, verifies its SHA-256 against the published manifest before staging anything, and reuses the redeploy's staged swap so live sessions survive. It refuses, rather than installs, a release that would require a new PTY supervisor - that upgrade ends every live session and is an announced, deliberate act.
Operations
  • mux, an HTTP CLI with stable human and JSON output, and mux doctor for local configuration, integration, ownership, tailnet, provider, telemetry, automation, and queue problems.
  • A copyable diagnostics bundle (sanitized config, remote state, firewall status, network counters, status-health aggregate, log tails) that contains no terminal bytes and no message content.
  • Durable operational telemetry for process ownership, quota samples and reset detection, compaction, and tool evidence, all recorded as observations with confidence rather than as authoritative facts.
  • Usage analytics that never sum agent spend, metered automation spend, and provider quota into one figure, and spending budgets denominated in tokens or dollars with an honest floor when cost is unmeasurable.
  • Traffic accounting, response compression, static precompression, and conditional Git reads.
Licensing and governance
  • Apache-2.0 with NOTICE and TRADEMARK.md, declared in package metadata as a PEP 639 license expression and carried into the wheel.
  • Contributions under a DCO sign-off rather than a CLA.
  • A generated THIRD-PARTY-NOTICES.md and a two-half license gate: a metadata check over the resolved dependency closure that runs in the test suite, and a payload check over the built desktop bundle. No GPL or AGPL code ships; the two LGPL libraries ship as replaceable source.