---
name: ssh-mac
description: SSH into a remote Mac over Tailscale (or any reachable host) to run commands, copy files, kick off background jobs, and open apps remotely. Use when the user says "ssh mac", "ssh into studio", "run on studio", "connect to my mac", "use my other mac", or asks to run commands / install software / do heavy compute on a remote Mac.
---


# SSH into Remote Mac

Patterns + safety rules for using a remote Mac from Claude Code. Works over Tailscale, LAN, or any SSH-reachable host. Keys must already be set up — no password prompts.

## Setup (one-time)

The skill assumes you've defined an SSH `Host` alias called `remote-mac` in `~/.ssh/config`. Add a block like this (replace the `HostName`, `User`, and key path with your own values):

```sshconfig
Host remote-mac
  HostName 100.x.y.z          # Tailscale IP, LAN IP, or DNS name
  User your-username
  IdentityFile ~/.ssh/id_ed25519
  ServerAliveInterval 30
```

Test it works:

```bash
ssh -o BatchMode=yes -o ConnectTimeout=5 remote-mac 'echo ok'
```

You can name the alias anything — `studio`, `mac`, `home-mac`, etc. If you do, substitute your alias for `remote-mac` in everything below.

### Why an alias and not a hard-coded IP

Skills are shared across machines and checked into dotfiles. Keeping your IP / username / key path in `~/.ssh/config` (which is local and private) means the skill itself stays portable and your personal info stays on your machine.

## Run a one-off command

```bash
ssh -o BatchMode=yes remote-mac 'COMMAND_HERE'
```

Use single quotes around the command. Escape dollar signs as `\$` if you want local shell expansion.

```bash
# Sanity check
ssh -o BatchMode=yes remote-mac 'whoami && hostname && pwd'

# Multi-line script
ssh -o BatchMode=yes remote-mac 'cd ~/some_dir && python3 script.py'

# Stream live output (drop BatchMode for progress bars / ttys)
ssh remote-mac 'long-running-command'

# Force a login shell so PATH includes Homebrew etc.
ssh remote-mac 'bash -lc "which ffmpeg"'
```

**Login shell vs non-login:** by default SSH runs a non-interactive shell that doesn't source `~/.zshrc`, so `/opt/homebrew/bin` won't be on PATH. Wrap in `bash -lc "..."` or `zsh -lc "..."` when you need the full environment.

## Copy files to/from remote

```bash
# Local → remote
scp -r /local/path remote-mac:~/remote_path

# Remote → local
scp -r remote-mac:~/remote_path /local/path

# Big trees: rsync is faster and resumable
rsync -avz --progress /local/path/ remote-mac:~/remote_path/
```

## Background jobs

```bash
# Kick off long job in background, detached from SSH
ssh remote-mac 'nohup python3 long_script.py > ~/logs/job.log 2>&1 & echo PID=$!'

# Check progress later
ssh remote-mac 'tail -50 ~/logs/job.log'

# See if it's still running
ssh remote-mac 'ps -p PID_HERE >/dev/null && echo running || echo done'
```

## Open apps / URLs on the remote Mac

```bash
ssh remote-mac 'open -a "App Name"'
ssh remote-mac 'open "https://example.com"'
ssh remote-mac 'open ~/Documents/some-file.pdf'
```

Useful when you want visual confirmation on the remote screen, or when a workflow needs an app to be foreground.

## Test connection

```bash
ssh -o BatchMode=yes -o ConnectTimeout=5 remote-mac 'echo ok'
```

If that fails, common fixes:

- **Tailscale not running:** `/Applications/Tailscale.app/Contents/MacOS/Tailscale status` on both machines.
- **Host is asleep or offline:** `ping -c 2 remote-mac`. Wake-on-LAN needs to be enabled separately.
- **Remote Login toggled off:** on the remote Mac, System Settings → General → Sharing → Remote Login.
- **Key not accepted:** re-copy your public key with `ssh-copy-id remote-mac` (will prompt for password once).
- **Host key changed after reinstall:** `ssh-keygen -R remote-mac` then retry.

## Computer-use tools do not work over SSH

You can't drive the remote Mac's GUI with System Events / keystroke / screenshot tools over SSH — those require an active GUI session with Accessibility permissions granted to the parent process. Options:

- **Use `open` commands** — launches apps, URLs, files. Works over SSH because no keystroke simulation is needed.
- **Use AppleScript `do script`** in Terminal.app on the remote — injects text into an existing tab without needing Accessibility:
  ```bash
  ssh remote-mac 'osascript -e "tell application \"Terminal\" to do script \"COMMAND\""'
  ```
- **Read Terminal output over SSH** with:
  ```bash
  ssh remote-mac 'osascript -e "tell application \"Terminal\" to get contents of front window"'
  ```
- **Grant Accessibility to `/usr/sbin/sshd-keygen-wrapper`** (or to `/bin/bash`) on the remote Mac if you truly need keystroke injection over SSH. This is a trust-sensitive change — do it deliberately, not automatically.

## Safety rules

- **Don't run `sudo` interactively.** It hangs the session waiting for a password. If the user explicitly authorizes a `sudo` action, tell them to run it themselves or use `NOPASSWD` in sudoers (their choice).
- **Don't install Homebrew without explicit consent.** It requires `sudo` and will block.
- **Don't `rm -rf` without confirming paths.** The remote is the user's actual machine, not a sandbox.
- **Don't paste secrets** into SSH arguments — they end up in the remote machine's shell history and process list. Use environment variables set server-side or `scp` a file.
- **Prefer absolute paths in arguments.** `~` expansion happens on the REMOTE side for `ssh remote-mac 'cd ~/x'` (good) but on the LOCAL side for `scp file remote-mac:~/x` (also good — but be aware). Absolute paths avoid confusion.
- **Wrap file paths with spaces in double quotes inside the single-quoted command**, e.g. `ssh remote-mac 'ls "~/My Folder"'`.

## Handy patterns

### Check what tools are installed

```bash
ssh remote-mac 'bash -lc "which ffmpeg yt-dlp python3 node brew 2>&1"'
```

### Get output directly into your local shell

```bash
REMOTE_HOSTNAME=$(ssh remote-mac 'hostname')
echo "Remote: $REMOTE_HOSTNAME"
```

### Heredoc for multi-line scripts

```bash
ssh remote-mac 'bash -s' <<'REMOTE_EOF'
set -e
cd ~/project
git pull
npm install
npm run build
REMOTE_EOF
```

### Run only if a file doesn't exist

```bash
ssh remote-mac 'test -f ~/data.csv || curl -o ~/data.csv https://example.com/data.csv'
```

### Port forwarding (to hit a service running on remote from local)

```bash
# Open http://localhost:8080 locally; it tunnels to remote's 8080
ssh -N -L 8080:localhost:8080 remote-mac
```

## When to use this skill vs local execution

Use the remote Mac when:
- You need an Apple Silicon GPU / Neural Engine for ML inference
- The workload is heavy (video render, whisper transcription, stem separation)
- The files you need live there already
- You want something to persist across your laptop going to sleep

Use local when:
- The task is fast (< 30s) and network latency would dominate
- You're iterating on code that lives locally
- The remote is offline
