When shell=True was removed for security, the command was parsed with shlex.split(posix=False) on Windows, which keeps the quote characters inside the tokens — so a quoted path like "C:\Program Files\app.exe" became an argv[0] containing literal quotes and CreateProcess couldn't find it, so app macros silently did nothing. Fix: on Windows pass the command string to Popen (shell=False) and let CreateProcess parse it (handles quoted paths, still no shell/metacharacter chaining); on POSIX keep shlex.split. Verified a real launch works and shell redirection stays blocked. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
MacroPad Server
A cross-platform macro management application with desktop and web interfaces. Create powerful command sequences with delays, key presses, and text input - accessible locally or remotely via a PWA-enabled web interface.
Features
Macro Capabilities
- Command Sequences: Build multi-step macros with:
- Text: Type text strings
- Keys: Press individual keys (Enter, Tab, Escape, etc.)
- Hotkeys: Key combinations (Ctrl+C, Alt+Tab, etc.)
- Wait: Insert delays between commands (in milliseconds)
- App: Launch applications or scripts
- Media & System Keys: Control playback and audio (volume up/down/mute, play/pause, next/previous track, stop) alongside regular keys
- Custom Images: Assign images to macros for easy identification
- Category Management: Organize macros into custom tabs
Interfaces
- Desktop GUI: Modern PySide6/Qt interface with visual command builder
- Web Interface: PWA-enabled for installation on any device
- System Tray: Minimize to tray, always accessible
Additional Features
- Relay Server Support: Access your macros securely over HTTPS from anywhere
- QR Code Generation: Quickly connect mobile devices
- Real-time Sync: WebSocket updates across all connected devices
- Offline Support: PWA caches for offline macro viewing
- Dark Theme: Modern dark interface throughout
- Auto-Migration: Existing macros automatically upgraded to new format
Requirements
- Python 3.11+
- Dependencies managed via
pyproject.toml
Core Dependencies
- PySide6 (Desktop GUI)
- FastAPI + Uvicorn (Web server)
- PyAutoGUI (Keyboard automation)
- Pillow (Image processing)
- pystray (System tray)
- qrcode (QR code generation)
- aiohttp (Relay server client)
Installation
Method 1: Using uv (Recommended)
# Install uv if not already installed
curl -LsSf https://astral.sh/uv/install.sh | sh
# Clone and install
git clone https://repo.anhonesthost.net/MacroPad/MP-Server.git
cd MP-Server
uv sync
Method 2: Using pip
git clone https://repo.anhonesthost.net/MacroPad/MP-Server.git
cd MP-Server
pip install -e .
Method 3: Pre-built Executables
- Go to the Releases page
- Download for your operating system:
- Windows:
macropad.exe - Linux:
macropad - macOS:
MacroPad Server.app
- Windows:
- Run the downloaded file
Important
Executables are unsigned and may trigger security warnings. You may need to:
- Windows: Click "More info" → "Run anyway" in SmartScreen
- Linux: Run
chmod +x macropadbefore executing- macOS: Right-click → Open, or adjust Gatekeeper settings
Usage
Running the Application
# If installed with uv
uv run python main.py
# If installed with pip
python main.py
Creating a Macro
- Click + Add Macro in the toolbar
- Enter a Name and optional Category
- Build your command sequence using the buttons:
- + Text: Add text to type
- + Key: Add a key press (enter, tab, escape, etc.)
- + Hotkey: Add a key combination (ctrl+c, alt+tab)
- + Wait: Add a delay in milliseconds
- + App: Add an application to launch
- Reorder commands with Up/Down buttons
- Click Save
Example: Login Macro
A macro that types a username, waits, presses Tab, types a password, and presses Enter:
[TEXT] myusername
[WAIT] 200ms
[KEY] tab
[TEXT] mypassword
[KEY] enter
Web Interface (PWA)
- Start the application (web server starts automatically on port 40000)
- Note the URL shown in the toolbar (e.g.,
http://192.168.1.100:40000/?token=...) - Open this URL on any device on your network
- Install as PWA:
- Mobile: Tap browser menu → "Add to Home Screen"
- Desktop: Click install icon in address bar
Important
The local web server now requires an access token. A per-install token is auto-generated and stored in
settings.json, and is embedded in the URL shown in the toolbar and in the QR code — so copying the URL or scanning the QR just works. Anyone with that URL can control your macros, so treat it like a password. By default the server also binds to your LAN; setweb.allow_lantofalsein settings to restrict access to localhost only.
The web interface provides full macro management:
- View and execute macros
- Create, edit, and delete macros directly from the web app — tap the + button to open the command-sequence builder (no desktop app required)
- Organize into categories
- Real-time sync across devices
System Tray
- Minimize window → App continues in tray
- Right-click tray icon:
- Show: Restore window
- Quit: Exit application
Relay Server (Remote Access)
Access your macros from outside your local network using a relay server:
- Click Settings (gear icon) in the toolbar
- Check Enable Relay Server
- Enter your relay server URL and password
- Click Save
Once connected, a relay URL will appear in the toolbar. Use this URL from any device with internet access. The relay provides:
- Secure HTTPS connection
- Macro browsing and execution
- PWA installation support
- Wake lock and fullscreen mode
Note
The relay web client is execute-only: remote devices can browse and trigger macros, but macro creation/editing is intentionally limited to the local network (the desktop app and the local web interface). This keeps macro authoring — which defines what runs on your computer — off the public internet.
Note
The relay password is stored in your OS keyring when one is available, falling back to the settings file (written with restricted
0600permissions) otherwise.
Note
You need access to a relay server. See MP-Relay for self-hosting instructions. The self-hosted relay now enforces login rate-limiting/lockout, keeps credentials out of URLs, and requires setting sane environment values — see the relay repo's
.env.example.
Command Types Reference
| Type | Description | Parameters |
|---|---|---|
text |
Types a text string | value: The text to type |
key |
Presses a single key | value: Key name (enter, tab, escape, f1-f12, etc.) |
hotkey |
Presses key combination | keys: List of keys (e.g., ["ctrl", "c"]) |
wait |
Delays execution | ms: Milliseconds to wait |
app |
Launches an application | command: Program and arguments to run (tokenized and executed directly — no shell) |
Example Application Commands
Important
appcommands are tokenized and the program is executed directly, without a shell. This closes a remote-code-execution risk, but it means shell features are not supported: command chaining (;,&&,|), output redirection (>), environment-variable expansion ($VAR,%VAR%), and shell built-ins will not work. Launching a program with arguments works exactly as shown below.
Windows
# Steam game
"C:\Program Files (x86)\Steam\steam.exe" steam://rungameid/2767030
# Chrome to website
"C:\Program Files\Google\Chrome\Application\chrome.exe" https://example.com
# Open folder
explorer.exe "C:\Users\YourUsername\Documents"
Linux
# Firefox
firefox https://example.com
# Steam game
steam steam://rungameid/2767030
# Terminal
gnome-terminal
macOS
# Safari
open -a Safari https://example.com
# VS Code
open -a "Visual Studio Code"
# Folder
open ~/Documents
Building Executables
Build platform-specific executables using PyInstaller:
# Install PyInstaller
pip install pyinstaller
# Windows (run on Windows)
pyinstaller macropad.spec
# Linux (run on Linux)
pyinstaller macropad_linux.spec
# macOS (run on macOS)
pyinstaller macropad_macos.spec
Note
PyInstaller cannot cross-compile. You must build on the target platform.
Project Structure
MP-Server/
├── main.py # Application entry point
├── config.py # Configuration constants
├── macro_manager.py # Macro storage and execution
├── web_server.py # FastAPI web server
├── relay_client.py # Relay server WebSocket client
├── pyproject.toml # Dependencies and build config
├── gui/ # PySide6 desktop interface
│ ├── main_window.py
│ ├── macro_editor.py
│ └── command_builder.py
├── web/ # PWA web interface
│ ├── index.html
│ ├── manifest.json
│ ├── service-worker.js
│ ├── css/styles.css
│ ├── js/app.js
│ └── icons/
└── macros.json # Macro storage (auto-created)
Migrating from v0.8.x
Existing macros are automatically migrated on first run. The old format:
{
"type": "text",
"command": "Hello",
"modifiers": {"enter": true}
}
Becomes the new command sequence format:
{
"type": "sequence",
"commands": [
{"type": "text", "value": "Hello"},
{"type": "key", "value": "enter"}
]
}
License
MIT License
Acknowledgments
Special thanks to CatArgent_ on Twitch for proofreading and providing valuable feedback.