Skip to content
HN On Hacker News ↗

How to set up your spare Mac for Claude Code to fully control - a step-by-step guide

▲ 251 points • 196 comments • by ykev • 4mo ago • HN discussion ↗

Pangram verdict · v3.3

We believe that this document is a mix of AI-generated, AI-assisted, and human-written content

36 %

AI likelihood · overall

Mixed
61% human-written 32% AI-generated
SEGMENTS · HUMAN 3 of 6
SEGMENTS · AI 3 of 6
WORD COUNT 1,703
PEAK AI % 95% · §4
Analyzed
Jul 18
backend: pangram/v3.3
Segments scanned
6 windows
avg 284 words each
Distribution
61 / 32%
human / AI fraction
Verdict
Mixed
Pangram v3.3

Article text · 1,703 words · 6 segments analyzed

Human AI-generated
§1 Human · 1%

claude-controls-mac

Here’s a full step-by-step guide on how to turn your spare Mac into an always-on machine Claude Code can fully control, with computer use enabled. You’ll be able to talk to it from your phone through the Claude app, or from your main Mac over SSH.

Why do this?

I wanted to create a separate environment Claude Code can control on its own, so I can delegate tasks I don’t necessarily want to run on my own machine - certain types of research tasks, and development tasks.

Claude Code, especially with the --dangerously-skip-permissions flag on, carries inherent risk when run on your main machine. You can eliminate / mitigate these risks by creating a separate environment on your spare Mac with everything it needs to have access to.

It has an added bonus of being able to talk to Claude Code anytime, anywhere from your phone. I’ve personally found it really useful because I often prefer to talk to Claude Code instead of regular Claude on the mobile app - Claude Code is often more capable.

The following guide assumes you have your main Mac as well as a spare Mac you can set up for this, but you should be able to take inspiration from it and apply it to any combination of two machines.

Why this setup?

First, let’s quickly address a few questions you might have.

Why not run it in a container?

I’m a big proponent of running it in a container - I even built an entire environment for doing so conveniently. However, I’ve found it has a few limitations. First, it still runs on your main machine, so it’s not completely separated. For example, network requests it sends still go through your main machine.

Second, there are limitations to the container’s capabilities. For example, I wanted my agent to be able to run Unity for game development, and there’s no easy way to do that in a container. The same goes for any other app that’s only available on a Mac - you won’t have access to it. That’s especially relevant if you want Claude Code to control these apps through computer use - clicking, dragging, and so on.

Why not use something like OpenClaw?

I personally like having access to the full, latest features of Claude Code.

§2 Human · 18%

I also like being able to control it from the Claude app - I’ve found it really convenient. And you get to use your Claude subscription usage if you happen to have one, which is an added bonus.

At the end of the day, running an agent with broad permissions is safer on a machine that has nothing to lose - but you get the benefit of being able to use a full Mac instead of a container. The approach here:

Use an old/spare Mac, not your main one. Create a fresh local account with no personal data and no Apple ID signed in, so the agent has nothing sensitive to reach. Drive it over SSH from your main Mac on your local network, and control it from your phone.

What you’ll need

A spare Mac (the target). Your everyday Mac (the source), on the same Wi-Fi.

§3 AI · 89%

1. Start fresh on the target Mac

Wipe it first (if it has any personal data)

You’ll be giving the agent full access to this machine, so it can reach anything stored on it. If there’s existing data you don’t want it to have access to, erase the machine first:

Macs that support it: System Settings -> General -> Transfer or Reset -> Erase All Content and Settings. Older Intel Macs: restart into Recovery (hold Cmd-R at boot), use Disk Utility to erase the internal drive, then reinstall macOS.

Optionally update to the latest macOS afterward (System Settings -> General -> Software Update).

Create a fresh, isolated account

Create a new local user account (System Settings -> Users & Groups). I recommend not signing into an Apple ID. Skip it during setup.

Make the account an admin (if you haven’t already)

The account needs admin rights or sudo will refuse to run.

System Settings -> Users & Groups -> set the account to Allow this user to administer this computer. If you ever need to repair it from another admin account: sudo dseditgroup -o edit -a <user> -t user admin

2. Enable Remote Login (SSH) on the target Mac

On the target, turn on SSH so the source Mac can connect:

sudo systemsetup -setremotelogin on

If the command fails with Turning Remote Login on or off requires Full Disk Access privileges, give your terminal app Full Disk Access first:

System Settings -> Privacy & Security -> Full Disk Access. Click +, then in the file picker go to Applications -> Utilities -> Terminal and add it. Quit and reopen the terminal, then rerun the command.

3. Passwordless sudo for the target account

This is so the agent (and your SSH commands) can run admin tasks without a password prompt each time. Run this once on the target. It asks for the login password this one time:

echo "<user> ALL=(ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/<user>-nopasswd >/dev/null sudo chmod 440 /etc/sudoers.d/<user>-nopasswd sudo visudo -cf /etc/sudoers.d/<user>-nopasswd

§4 AI · 95%

# validate - must print 'parsed OK'

This creates a small rule file telling the Mac that <user> can run sudo without a password prompt:

line 1 writes the rule into /etc/sudoers.d/. line 2 makes it read-only - sudo ignores the file otherwise. line 3 validates the syntax; a typo in a sudoers file can lock you out of sudo entirely, so it must print parsed OK.

After this, sudo runs with no prompt - test with sudo -n true, which succeeds silently if passwordless sudo works.

4. Find the target’s address (hostname or IP)

You can reach the target by either a hostname or an IP. I recommend using the hostname: it stays the same, while the IP can change.

Hostname (recommended). Run on the target:

scutil --get LocalHostName # prints the hostname, e.g. MacBook-Pro

Add .local to form the address: <target-host>.local. You can also read it from System Settings -> General -> Sharing, shown as Local hostname.

Give the target a unique name. Each Mac needs a .local name that’s unique on your network. If two machines share a name, the address can point to the wrong Mac. Make sure the target’s name is unique - rename it if needed:

sudo scutil --set LocalHostName newmacbook # -> newmacbook.local

IP address (not recommended). Run on the target:

ipconfig getifaddr en0 # e.g. 192.168.1.80

Note that the IP can change after a reboot or after a certain amount of time.

Throughout the rest of this guide, replace <user> with the target account name and <target-host> with the hostname from above, so the address is <user>@<target-host>.local. You could also instead use an IP in place of <target-host>.local.

5. Set up passwordless SSH from the source Mac

On the source Mac, create an SSH key (skip if you already have one):

ssh-keygen -t ed25519

Install your public key on the target.

§5 Human · 19%

This asks for the target account’s login password once:

ssh-copy-id <user>@<target-host>.local

Test it - this should print the target username with no password prompt:

ssh <user>@<target-host>.local whoami

6. Keep the target awake

By default macOS sleeps after ~10 minutes idle, even when plugged in, which takes it off the network. To make it never sleep, run this on the target (or over SSH from the source):

sudo pmset -c sleep 0 # never system-sleep while plugged in (-c = on charger) sudo pmset -c disablesleep 1 # also prevents sleep with the lid closed (clamshell) sudo pmset -c displaysleep 0 # keep the display on too

Verify:

pmset -g | grep -iE 'sleep'

sleep 0, SleepDisabled 1, and displaysleep 0 in the output confirm it worked.

If the machine runs on battery sometimes, use -a instead of -c to apply to all power sources (at the cost of battery drain).

The screen can still lock when the screen saver kicks in. Stop the screen saver from ever starting so it never locks on its own:

defaults -currentHost write com.apple.screensaver idleTime 0

7. Clipboard sync over SSH

macOS ships pbcopy (write clipboard) and pbpaste (read clipboard). Piped over SSH, they can move the clipboard between machines - encrypted, peer-to-peer, no Apple ID or third-party service.

clip.sh wraps this into one command with two subcommands, and adds image support on top of pbcopy/pbpaste (which are text-only). Install it as a script on your PATH on the source Mac, and point it at the target host with IC_BOX (“ic” standing for “isolated claude”):

curl -fsSL https://raw.githubusercontent.com/ykdojo/claude-controls-mac/main/clip.sh -o ~/.local/bin/clip chmod +x ~/.local/bin/clip export IC_BOX="<user>@<target-host>.local" # add to ~/.zshrc

Usage:

clip send - this Mac’s clipboard → the target (text or image).

§6 AI · 72%

For an image you can paste it straight into a Claude Code session on the target with Ctrl-V. clip get - the target’s clipboard → this Mac (text or image).

8. Install Claude Code on the target Mac

Send the install command over and run it. From the source Mac you can push it straight to the target’s clipboard, or run it remotely. The following command installs a specific version, but you can also install latest or stable if you’d like:

ssh <user>@<target-host>.local 'curl -fsSL https://claude.ai/install.sh | bash -s -- 2.1.201'

The native installer may warn that ~/.local/bin is not on PATH. Fix it on the target by adding it to ~/.zshenv (not ~/.zshrc) - .zshenv is read by every zsh, including non-interactive ones:

ssh <user>@<target-host>.local 'echo '\''export PATH="$HOME/.local/bin:$PATH"'\'' >> ~/.zshenv'

9. Set up an opinionated, Claude Code-friendly environment (optional)

This optional step applies a set of opinionated defaults via setup-claude-env.sh - shell aliases, the DX plugin, settings.json tweaks, the GitHub CLI, and (opt-in) Playwright MCP and yt-dlp. Every item is toggleable; see the full list in claude-env-components.md.

Interactively on the target - shows a checklist of every item (core pre-checked, opt-ins unchecked) so you can pick any combination. Download the script onto the target and run it:

ssh -t <user>@<target-host>.local \ 'curl -fsSL https://raw.githubusercontent.com/ykdojo/claude-controls-mac/main/setup-claude-env.sh -o setup-claude-env.sh && bash setup-claude-env.sh'

Non-interactively - the script goes into this mode if it detects a non-interactive environment or you supply at least one flag.