If the one-command install didn't work, you're in the right place. This article covers every failure we've seen when installing Matrix Desktop on a headless Mac over SSH — and the exact fix for each one.

If you haven't tried the install yet, start with the headless Mac setup guide first. Come back here if something goes wrong.

"Operation not permitted" When Copying

The app is already installed and running, so copying directly over the active bundle can fail.

Fix: Use the current installer. It stages and verifies the replacement before it stops the running app:

Terminal (SSH session)
MATRIX_INSTALLER="$(mktemp -t matrix-desktop-install)" && curl --fail --location --proto '=https' --tlsv1.2 https://matrix.watch/install.sh -o "$MATRIX_INSTALLER" && /bin/bash "$MATRIX_INSTALLER" && rm -f "$MATRIX_INSTALLER"

Do not delete the working installation before the replacement has passed validation.

Tip: The same installer handles both fresh installs and updates.

"Resource busy" When Mounting DMG

A previous DMG mount is still attached from a failed install attempt.

Fix: Detach the stale mount:

Terminal (SSH session)
hdiutil detach "/Volumes/Matrix Desktop"
Tip: Never copy a hard-coded /dev/diskN from a guide; disk identifiers are different on every Mac. The current installer mounts at a unique temporary path and avoids this conflict.

Commands Break When Pasted Over SSH

Multi-line commands with backslash (\) continuations can split into separate commands in some terminal emulators (Warp, iTerm pasting into SSH sessions, Tailscale SSH). You'll see errors like zsh: no URL specified, command not found: -R, or only the first line executes.

Fix: Use a single-line version of the install command with no line breaks:

Terminal (SSH session)
MATRIX_INSTALLER="$(mktemp -t matrix-desktop-install)" && curl --fail --location --proto '=https' --tlsv1.2 https://matrix.watch/install.sh -o "$MATRIX_INSTALLER" && /bin/bash "$MATRIX_INSTALLER" && rm -f "$MATRIX_INSTALLER"
Tip: The command is intentionally one line so it survives SSH paste handling.

Display Is Asleep

system_profiler SPDisplaysDataType shows Display Asleep: Yes. The open command may fail or the app may launch but not render because macOS has suspended the display pipeline.

Fix: Wake the display before launching:

Terminal (SSH session)
caffeinate -u -t 5

Headless Macs put their virtual display to sleep after a few minutes of inactivity. The -u flag simulates a user wake event. Run this before open in your install command.

No GUI Session / WindowServer Not Running

The open command fails silently or errors because there's no active GUI session. This happens when:

Fix: Enable either auto-login or Screen Sharing:

Tip: A dummy HDMI plug also helps macOS maintain a proper WindowServer session even when no one is connected via Screen Sharing.

Gatekeeper Blocks the App

You see "damaged and can't be opened" or "developer cannot be verified" when launching over SSH.

Fix: Do not bypass Gatekeeper or clear security attributes. Verify the installed app, then reinstall from the validated release if assessment fails:

Terminal (SSH session)
codesign --verify --deep --strict --verbose=2 "/Applications/Matrix Desktop.app" && spctl --assess --type execute --verbose=2 "/Applications/Matrix Desktop.app"

"login item UNKNOWN" From osascript

When you run the osascript command to add a login item, it returns login item UNKNOWN. This looks like an error but it's not — the login item was created successfully. macOS returns this for apps that aren't currently running or for the first registration.

Verify it worked by checking System Settings > General > Login Items, or just reboot and confirm the app starts automatically.

Rain Not Visible After Launch

The process is running (ps aux | grep -i matrix shows it) but you don't see rain on the desktop through Screen Sharing.

Possible causes:

Check if it's running:

Terminal (SSH session)
ps aux | grep -i "[M]atrix"

Low Resolution / Blocky Rain

The app auto-upgrades resolution on headless displays, but if you want Retina quality: use a dummy HDMI plug ($8 on Amazon) or BetterDisplay ($21.50) for full control over virtual display resolution.

The Bulletproof Install Command

The validated installer downloads, verifies, stages, replaces, wakes the display, and launches the app without deleting a good installation first. This command also adds the successful installation as a login item:

Terminal (SSH session)
MATRIX_INSTALLER="$(mktemp -t matrix-desktop-install)" && curl --fail --location --proto '=https' --tlsv1.2 https://matrix.watch/install.sh -o "$MATRIX_INSTALLER" && /bin/bash "$MATRIX_INSTALLER" && rm -f "$MATRIX_INSTALLER" && osascript -e 'tell application "System Events" to make login item at end with properties {path:"/Applications/Matrix Desktop.app", hidden:false}'
Tip: This is safe for fresh installs and updates because validation and staging happen before replacement.

Claude Code Troubleshooting Prompt

A prompt you can paste into Claude Code that diagnoses and fixes everything automatically:

Claude Code prompt
Troubleshoot Matrix Desktop on this Mac. Check whether the app is running and whether /Applications/Matrix Desktop.app passes codesign --verify --deep --strict and spctl --assess --type execute. Never clear quarantine or target a hard-coded /dev/diskN. If reinstalling is needed, use https://matrix.watch/install.sh so the DMG, signature, and Gatekeeper assessment are validated and the new app is staged before the existing copy is replaced. Wake the display, launch the app, verify it is running, and show me the final status.