AeroMux gives AeroSpace a persistent macOS sidebar. It keeps your non-empty workspaces visible, highlights the active workspace and window, and lets you click a listed window to focus it.
This is an early release MVP. It now ships as a GitHub Releases DMG and can still be built locally with Swift Package Manager.
- Shows non-empty AeroSpace workspaces in a persistent left sidebar
- Highlights the focused workspace and focused window
- Lists windows inside each workspace by app name
- Lets you click a row to focus that window through the AeroSpace CLI
- Adds a menu bar item for show/hide, refresh, and quit
- Lets you change the sidebar width from the menu bar
- Lets you enable compact mode from the menu bar
- Lets you enable launch at login from the menu bar
- Polls AeroSpace every second by default
- Supports a localhost refresh hook for lower-latency updates
- Detects whether your AeroSpace left gap is large enough to avoid overlap
- Lets you keep workspace positions stable instead of moving the active one to the top
- Stores sidebar settings in
~/.config/aeromux/settings.json - Supports local workspace titles/descriptions from
~/.config/aeromux/workspaces.json
AeroSpace gives you fast keyboard-driven workspace management. AeroMux adds a constant visual rail so you can see what is open and jump to a specific window without losing the tiling workflow.
Before you try it, the current behavior is worth stating clearly:
- The sidebar is anchored to the left edge of the main monitor
- The clean layout depends on an AeroSpace
outer.leftgap reservation - If the gap is missing or too small, AeroMux falls back to a floating overlay
- There is no Preferences window yet
- Release DMGs are currently ad hoc signed but not notarized
- macOS 13 or newer
- AeroSpace installed and already working on your machine
aerospaceavailable onPATHin the same environment used to launch AeroMux- A Swift 6 toolchain that can build macOS apps with Swift Package Manager
Quick sanity checks:
sw_vers -productVersion
aerospace --version
swift --version
which aerospaceIf which aerospace prints nothing, AeroMux will fail to talk to AeroSpace.
The preferred install path is the latest DMG from GitHub Releases.
Current release builds are ad hoc signed but not notarized, so macOS may warn on first launch. If that happens, open the app with Finder's Open flow and confirm the warning once.
git clone https://github.com/raghavendra-talur/aeromux.git
cd aeromux
swift build
swift runThat launches AeroMux as a background-style accessory app and opens the sidebar window.
If you prefer to build once and launch the executable yourself:
swift build
./.build/debug/AeroMuxIf you launch it in the foreground, stop it with Ctrl-C.
If you launch it in the background:
./.build/debug/AeroMux &You can stop it with:
pkill AeroMuxTo avoid the sidebar covering tiled windows, reserve space on the left side of your main monitor:
[gaps]
outer.left = [{ monitor.main = 260 }, 0]260 matches the current default sidebar width. If you use a different width in code later, keep the two values aligned.
You can change the width from the AeroMux menu bar item or by editing settings.json directly. If you increase the width, make sure outer.left is at least that large.
When AeroMux can confirm that the reserved left gap is wide enough, it drops to a normal window level. If it cannot confirm that reservation, or the gap is too small, it stays floating and shows a warning in the UI.
Polling mode works without any extra setup. If you want faster updates after AeroSpace events, add a hook that hits AeroMux's local refresh endpoint:
curl -fsS -X POST http://127.0.0.1:39173/refresh >/dev/null 2>&1 || trueA helper script is included at scripts/aerospace-refresh-hook.sh.
The refresh listener binds only to 127.0.0.1:39173.
AeroMux stores sidebar-specific settings in:
~/.config/aeromux/settings.jsonIf XDG_CONFIG_HOME is set, AeroMux uses:
$XDG_CONFIG_HOME/aeromux/settings.jsonThe file is created automatically on first run. Current keys:
{
"compactMode": false,
"launchAtLogin": false,
"pinActiveWorkspaceFirst": false,
"sidebarWidth": 260
}Behavior:
sidebarWidthis the sidebar width in pixels and is clamped to whole numbers between100and600compactModeenables a denser sidebar layout with slightly smaller textpinActiveWorkspaceFirstcontrols whether the focused workspace is moved to the toplaunchAtLogincontrols whether AeroMux asks macOS to launch it at login- changes made in the file are picked up the next time AeroMux launches
- changing the width also means AeroSpace
outer.leftshould be at least that wide
AeroMux can read custom titles and descriptions for AeroSpace workspaces from:
~/.config/aeromux/workspaces.jsonIf XDG_CONFIG_HOME is set, AeroMux uses:
$XDG_CONFIG_HOME/aeromux/workspaces.jsonThe file is created automatically on first run and populated with the currently discovered AeroSpace workspaces:
{
"workspaces": [
{
"workspace": "1",
"title": "1",
"description": null
}
]
}Behavior:
workspacemust match the AeroSpace workspace name exactlytitlereplaces the defaultTask <workspace>labeldescriptionis shown under the title- when a custom title is present, AeroMux also shows the raw workspace name underneath as
Workspace <name> - you can edit title and description directly from the sidebar using the pencil button on each workspace card
AeroMux currently relies on these AeroSpace CLI commands:
aerospace list-workspaces --focused --jsonaerospace list-workspaces --focused --format %{workspace}aerospace list-windows --focused --jsonaerospace list-windows --all --format %{window-id}\t%{app-name}\t%{window-title}\t%{workspace}\t%{app-bundle-id}aerospace list-monitors --focused --jsonaerospace focus --window-id <id>aerospace config --config-path
If a future AeroSpace release changes those flags or output formats, AeroMux may need updates.
Make sure aerospace is installed and visible on PATH for the process that launches AeroMux:
which aerospace
aerospace --versionIf AeroSpace works in one shell but not another, fix your shell startup files or launch AeroMux from an environment where aerospace resolves correctly.
That means one of these is true:
outer.leftis not configured- the reserved left gap is smaller than the sidebar width
- AeroMux could not read your AeroSpace config path
Start with:
aerospace config --config-pathThen confirm your config contains a left gap reservation like:
[gaps]
outer.left = [{ monitor.main = 260 }, 0]If you changed sidebarWidth in settings.json or from the menu bar, use that number instead of 260.
Your installed AeroSpace CLI may not support aerospace focus --window-id <id> yet, or it may have changed behavior.
Try:
aerospace focus --helpIf that flag is unsupported in your version, AeroMux can still display state but window focusing will fail.
Check the basics first:
- AeroSpace is running
- you currently have a focused workspace
- you have at least one managed window open
aerospace list-windows --allreturns output in your shell
- Main monitor only
- Left sidebar only
- No Preferences window yet
- Release builds are not notarized yet
- No published compatibility matrix yet for Intel Macs or multiple AeroSpace versions
This is not a full compatibility matrix yet. It is the environment currently verified in this repository:
- macOS 26.2 (
BuildVersion 25C56) - Apple Silicon
arm64 - AeroSpace
0.20.3-Beta(6dde91ba43f62b407b2faf3739b837318266e077) - Apple Swift
6.2.3
The repository is currently tagged v0.1.
This should be treated as an early public MVP rather than a polished packaged release.
Issues and compatibility reports are useful, especially for:
- macOS version differences
- Intel Mac behavior
- AeroSpace version compatibility
- refresh-hook integration examples
- ideas for packaging and a better app lifecycle
If you are maintaining this repository, local packaging and tag-based GitHub Releases are documented in docs/RELEASING.md.
General local contributor workflow is documented in docs/DEVELOPMENT.md.
