Skip to main content

wsmux

Workspace launcher for macOS. Open and close entire project environments with one command.

One config file. One command. Your entire workspace — editors, browsers, terminals, docker, apps — opens exactly where you left it.

Install

pip install wsmux

Or install from source:

git clone https://github.com/safeersoft/wsmux.git
cd wsmux
pip install .

The CLI command is mux.

Quick Start

# Create a config in your project
cd ~/my-project
mux --init .

# Edit .mux.json to match your setup, then:
mux .                # Open everything
mux -s .             # Save window positions + close
mux .                # Reopen — everything is where you left it

Commands

Command What it does
mux . Open workspace from .mux.json
mux -s . Save current state (new tabs, positions) then close
mux -ss . Quick close — no config update
mux -c . Capture current desktop into .mux.json
mux -l . Dry run — show what would open
mux --init . Create a starter .mux.json

Named Projects

Register projects to open them from anywhere:

mux --add myapp ~/projects/myapp    # Register
mux myapp                            # Open from anywhere
mux -s myapp                         # Save + close from anywhere
mux --projects                       # List registered projects
mux --remove myapp                   # Unregister

Config Format

.mux.json in your project root:

{
  "name": "My Project",
  "apps": [
    {
      "type": "vscode",
      "paths": ["./frontend", "./backend"],
      "windows": {
        "./frontend": {"position": [0, 0], "size": [960, 1080]},
        "./backend": {"position": [960, 0], "size": [960, 1080]}
      }
    },
    {
      "type": "browser",
      "app": "Microsoft Edge",
      "urls": ["http://localhost:3000", "https://github.com/me/repo"],
      "window": {"position": [1920, 0], "size": [1680, 1050]}
    },
    {
      "type": "terminal",
      "app": "Terminal",
      "tabs": [
        {
          "name": "server",
          "command": "npm run dev",
          "cwd": "./backend",
          "window": {"position": [0, 600], "size": [800, 400]}
        }
      ]
    },
    {
      "type": "docker",
      "services": ["postgres", "redis"],
      "cwd": "./backend"
    },
    {
      "type": "app",
      "name": "Postman"
    }
  ]
}

Entry Types

Type What it opens Key fields
vscode VS Code / Cursor windows paths, command ("cursor"), windows (geometry)
browser Browser with tabs in isolated window app, urls, window (geometry)
terminal Terminal.app / iTerm2 tabs tabs[].name, tabs[].command, tabs[].cwd, tabs[].window
docker Docker Compose services services, cwd, file
app Any macOS app name, args
script Shell command command, cwd, stop_command

Window Positions

Mux remembers where every window was — position, size, and which monitor.

  • Auto-capture: mux -s saves current positions before closing
  • Manual capture: mux -c snapshots your current desktop
  • Restore: mux . reopens windows at their saved positions
  • Multi-monitor: positions use macOS unified coordinates, so windows restore to the correct monitor

Save Behavior (mux -s)

When closing with -s, mux compares your current desktop against the saved config:

  • Existing entries: geometry is updated silently
  • New entries (new browser tabs, apps): you're prompted for each one:
New entries detected:

    + [App] Postman  [y/n/i] (yes/no/ignore forever): y
      ✓ Added

    + [Microsoft Edge] reddit.com + 2 more tabs  [y/n/i] (yes/no/ignore forever): i
      ✗ Ignored forever: URL pattern 'reddit.com'
  • y — add to config
  • n — skip this time
  • i — skip and add to global ignore (never captured again)

Global Ignore

~/.mux/ignore.json — patterns that are never captured:

{
  "apps": ["Slack"],
  "urls": ["chatgpt.com", "claude.ai", "reddit.com"],
  "paths": []
}

Browser Isolation

Each project opens its browser tabs in a new isolated window. Running mux for two different projects won't mix their tabs together.

Requirements

  • macOS (uses AppleScript for window management)
  • Python 3.10+
  • Terminal needs Accessibility permission (System Settings > Privacy & Security > Accessibility) for window positioning

Data Files

All stored in ~/.mux/:

File Purpose
projects.json Named project registry
ignore.json Global ignore patterns
states/ Last-opened state per project

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

wsmux-0.1.0.tar.gz (19.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

wsmux-0.1.0-py3-none-any.whl (18.0 kB view details)

Uploaded Python 3

File details

Details for the file wsmux-0.1.0.tar.gz.

File metadata

  • Download URL: wsmux-0.1.0.tar.gz
  • Upload date:
  • Size: 19.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.4

File hashes

Hashes for wsmux-0.1.0.tar.gz
Algorithm Hash digest
SHA256 2a25550da27d59f1fe946709d803e98a6fd3b5740f23c51f51a9d526d8613ae8
MD5 c97cb1e4401a3ad9c3090fc075f4f089
BLAKE2b-256 4fcc789daa3ad54102c116ae58c6c01b14c4e09248eb67deebf52051d2039e43

See more details on using hashes here.

File details

Details for the file wsmux-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: wsmux-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 18.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.4

File hashes

Hashes for wsmux-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e6c98aa040f229f5d6633ac421075ba00cee087be5dfbdd2b8a70714200aa7a0
MD5 6e6a6cefb30d0c35f7852320f20d89b7
BLAKE2b-256 18876552a10d390bb604712bb5abfacce5696029af3613300334b62776eb5a01

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page