A modern mouse and keyboard macro recording and playback application for Linux (Wayland and X11), Windows, and macOS.
| Recording | Playback | Text Expansion |
|---|---|---|
![]() |
![]() |
![]() |
| Shortcuts | Scheduled Tasks | Settings |
![]() |
![]() |
![]() |
- Linux (X11 & Wayland) β
- Windows β
- macOS β
About Mouse Position Tracking on Wayland
CrossMacro works on all Wayland compositors. However, due to Wayland's security model, how we track mouse position varies:
Absolute positioning β We can read the cursor position directly. Supported on:
- Hyprland (via IPC)
- KDE Plasma (via D-Bus)
- GNOME (via Shell Extension)
Relative positioning (fallback) β For other compositors, the cursor resets to the top-left corner (0,0) at the start of every recording and playback session. This is needed because we can't read the current mouse position, so we use a known reference point to calculate movements.
Both modes work reliably for macro recording and playback.
- Mouse Event Recording: Record mouse clicks and movements
- Keyboard Event Recording: Record keyboard key presses
- Text Expansion: Create text shortcuts for quick insertions (e.g. :mail -> email@example.com)
- Shortcuts: Assign macros to keyboard keys, mouse buttons, or combinations for instant execution
- Toggle mode: Press to start, press again to stop
- Run while held: Runs while the key is pressed, stops on release
- Loop support with customizable repeat count and delay
- Scheduling: Run macros automatically at specific times or intervals
- Macro Editor: Powerful built-in editor with undo/redo, smart coordinate capture, and action reordering to fine-tune your macros
- Playback: Replay recorded macros with pause/resume support
- Loop Mode: Continuously repeat macros with customizable repeat count and delay
- Speed Control: Adjust playback speed from 0.1x to 10.0x
- File Operations: Save/load macros in .macro format (you choose where to save)
- Themes: Customize the look with Classic, Latte, Mocha, Dracula, and Nord themes
- System Tray Icon: Minimize to tray and control macros from system tray (optional)
- Global Hotkeys: Customizable global hotkey support
- F8: Start/Stop recording
- F9: Start/Stop playback
- F10: Pause/Resume playback
Debian / Ubuntu (.deb)
# Download from GitHub Releases, then:
sudo apt install ./crossmacro-*_amd64.deb
# Add yourself to the crossmacro group (required for daemon communication)
sudo usermod -aG crossmacro $USER
# Enable and start the background service (important for daemon functionality)
sudo systemctl enable --now crossmacro.service
# Reboot your system for group changes to take effect, then start the appFedora / RHEL (.rpm)
# Download from GitHub Releases, then:
sudo dnf install ./crossmacro-*.x86_64.rpm
# Add yourself to the crossmacro group (required for daemon communication)
sudo usermod -aG crossmacro $USER
# Enable and start the background service (important for daemon functionality)
sudo systemctl enable --now crossmacro.service
# Reboot your system for group changes to take effect, then start the appArch Linux
Available on the AUR:
# Using yay
yay -S crossmacro
# Using paru
paru -S crossmacro
# Enable and start the background service (important for daemon functionality)
sudo systemctl enable --now crossmacro.service
# After installation, add yourself to the group
sudo usermod -aG crossmacro $USER
# Reboot your system for group changes to take effect, then start the appNixOS
Run directly:
nix run github:alper-han/CrossMacroNote:
nix rundoes not install the background daemon. For it to work, you must manually configure permissions (add yourself toinputgroup and set up udev rules) as described in the AppImage section below.
Add to your configuration:
Add this to your flake.nix inputs:
inputs.crossmacro.url = "github:alper-han/CrossMacro";Then in your NixOS configuration:
{ inputs, ... }: {
imports = [ inputs.crossmacro.nixosModules.default ];
programs.crossmacro = {
enable = true;
users = [ "yourusername" ]; # Add users who should access CrossMacro
};
}Note: The NixOS module automatically sets up the daemon service, user, groups, and adds specified users to the
crossmacrogroup. Reboot your system for group changes to take effect.
AppImage (Portable)
This method allows you to run the app without installing anything extra. Since AppImages run on FUSE, we recommend configuring User Group Permissions for the best experience.
β οΈ Security Warning: Adding your user to theinputgroup grants your user account direct access to all input devices (keystrokes, mouse moves). This bypasses the secure daemon isolation typically recommended for Linux/Wayland, but is required for the AppImage to function without a system service.
Setup Instructions (Required) π οΈ This allows you to run the app normally (just double-click) without needing sudo.
- One-time setup (Run in terminal):
# Add udev rule for uinput access echo 'KERNEL=="uinput", GROUP="input", MODE="0660", OPTIONS+="static_node=uinput"' | sudo tee /etc/udev/rules.d/99-crossmacro.rules # Reload rules sudo udevadm control --reload-rules && sudo udevadm trigger # Add your user to input group sudo usermod -aG input $USER
- Restart your computer (Important for group changes to take effect).
- Run the App:
chmod +x CrossMacro-*.AppImage ./CrossMacro-*.AppImage
Windows
Download the .exe file from GitHub Releases and run it directly.
Alternative (Winget):
winget install -e --id AlperHan.CrossMacroNote: No installation required. The executable is self-contained and doesn't require .NET to be installed.
macOS
Download the .dmg file from GitHub Releases.
- Open the
.dmgfile. - Drag CrossMacro to your Applications folder.
- Keep the app open in Applications folder. (Double check security settings if it doesn't open).
Note: Requires Accessibility Permissions to record and play macros. You will be prompted to grant these permissions on first run.
β οΈ "App is damaged" Error: If macOS prevents opening the app, run this command in Terminal to bypass Gatekeeper quarantine:xattr -cr /Applications/CrossMacro.app
Manual Build (Development)
Requirements: .NET 10 SDK
# Clone the repository
git clone https://github.com/alper-han/CrossMacro.git
cd CrossMacro
# Install daemon (Linux only)
sudo ./scripts/daemon/install.sh
# Run the application
dotnet run --project src/CrossMacro.UI/Linux (Wayland)
CrossMacro uses a secure daemon architecture on Wayland:
βββββββββββββββββββ IPC Socket ββββββββββββββββββββββββ
β CrossMacro UI β βββββββββββββββββββΊ β CrossMacro Daemon β
β (Your User) β β (System Service) β
βββββββββββββββββββ ββββββββββββββββββββββββ
β
βΌ
/dev/input/* (read)
/dev/uinput (write)
- Daemon runs as a system service with
inputgroup privileges - UI runs as your normal user, communicates via Unix socket
- Security: Wayland's strict security model prevents direct input access, so a privileged daemon handles input capture/simulation
- Position: Mouse position is obtained via compositor-specific protocols (Hyprland IPC, KDE D-Bus, GNOME Shell Extension)
Linux (X11)
CrossMacro uses native X11 APIs for direct input handling on X11:
βββββββββββββββββββββββββββββββββββββββ
β CrossMacro UI β
β (Single Process Architecture) β
βββββββββββββββββββββββββββββββββββββββ
β
βΌ
X11 Server (Xlib)
ββ XTest Extension (simulation)
β ββ XTestFakeKeyEvent()
β ββ XTestFakeButtonEvent()
β ββ XTestFakeMotionEvent()
β
ββ XInput2 Extension (capture)
ββ XI_RawKeyPress/Release
ββ XI_RawButtonPress/Release
ββ XI_RawMotion
- Single Process: No separate daemon required (but daemon is still supported for unified experience)
- XTest: Simulates keyboard, mouse, and scroll events directly to X server
- XInput2: Captures raw input events from all master devices
- Position:
XQueryPointer()provides accurate cursor position - Permissions: Runs with normal user privileges through X protocol
Windows
CrossMacro uses Windows API hooks for input handling:
βββββββββββββββββββββββββββββββββββββββ
β CrossMacro UI β
β (Single Process Architecture) β
βββββββββββββββββββββββββββββββββββββββ
β
βΌ
Windows API (User32.dll)
ββ SendInput() (simulation)
ββ SetWindowsHookEx() (capture)
- Single Process: No separate daemon required
- API Hooks: Uses low-level keyboard and mouse hooks
- Permissions: Runs with normal user privileges
macOS
CrossMacro uses CGEvent Taps (Core Graphics) for input handling:
βββββββββββββββββββ
β CrossMacro UI β
βββββββββββββββββββ
β
βΌ
Core Graphics (CGEvent)
ββ CGEventCreate() (simulation)
ββ CGEventTapCreate() (capture)
- Native Integration: Uses native macOS APIs for high performance.
- Permissions: Requires Accessibility API access (System Settings > Privacy & Security > Accessibility).
GNOME: Extension Required
CrossMacro requires a GNOME Shell extension to read mouse position on Wayland. The extension is automatically installed and enabled when you first run CrossMacro.
Note: You need to log out and log back in for the extension to take effect after the first installation.
Note: When using AppImage (without the system daemon), this extension is still required for recording mouse positions. The app will handle input simulation directly via the permissions granted.
CrossMacro will show a warning if the extension is not active.
Daemon Not Running
Check daemon status:
systemctl status crossmacro.serviceIf not running:
sudo systemctl start crossmacro.service
sudo systemctl enable crossmacro.service # Auto-start on bootPermission Denied Errors
Ensure you're in the crossmacro group:
groups | grep crossmacroIf not, add yourself:
sudo usermod -aG crossmacro $USER
# Reboot your system for group changes to take effect!Polkit Not Available (Minimal/Embedded Systems)
The daemon requires polkit for authorization. If your system doesn't have polkit installed (some minimal or embedded distributions), the daemon will reject all connections.
Check if polkit is installed:
which pkcheck
# or
pkcheck --versionIf polkit is not available:
- The daemon won't work without polkit
- Use the AppImage instead with
inputgroup permissions (see AppImage section above)
Note: Most desktop Linux distributions (Fedora, Ubuntu, Arch, etc.) include polkit by default. This is typically only an issue on minimal server installations or embedded systems.
Enable Debug Logging
If something isn't working, checking the logs is the best place to start. Both the daemon and UI can provide useful information.
Daemon logs (debug level):
sudo systemctl kill -s USR1 crossmacro
journalctl -u crossmacro -fSend the signal again to switch back to normal logging.
UI logs: Run the application from terminal to see output directly.
Look for permission errors, device detection issues, or any error messages that point to the problem.
Input Not Working (Keyboard or Mouse)
If your keyboard or mouse inputs aren't being captured, first check the daemon and UI logs (see Enable Debug Logging above).
One known cause is GPU Screen Recorder, which locks input devices exclusively. Stop it temporarily:
systemctl --user stop gpu-screen-recorder
pkill -9 -f gpu-screen-recorderRestart after you're done:
systemctl --user start gpu-screen-recorder




