Mac from zero

For a Mac that has never had KernelHub. Every step can be copied, and every step says what success looks like: install Node, install KernelHub with one line, log in a Runtime, pair your phone, send a real task, watch it deliver. No sudo anywhere.

How to use this page
Work from top to bottom, one step at a time. Every step tells you where to open, which line to copy, what success looks like, and what to do if you don't see it. Each command block has a Copy button: click it, paste into Terminal, press Enter. With internet access you only need sections 1 and 2. Prefer the drag-to-Applications app: section 4. Blocked network: section 6.

1 · Before you start: what this Mac is missing

You have a Mac that has never had KernelHub on it (Apple silicon or Intel), and you want to get to "send work from my phone, have this Mac do it". First, what it ships with and what it lacks:

ThingOn a fresh Mac?Notes
Terminal app and zshYesEvery command on this page is written for the default zsh.
curl / shasum / tarYesBuilt in. This page uses them to download and verify.
Node.js / npmNoThe single most important row on this page. The installer does not install Node for you. Without npm it cannot install an AI coding tool (a Runtime), and you end up with "KernelHub is installed, but it cannot run a single task".
~/.local/bin on PATHNoKernelHub and the Node from this page both live there. If it isn't on PATH, Terminal can't find icloser or node. Section 2, step 3 fixes it with one line.
git (Command Line Developer Tools)Not installedThe first time something uses git, macOS asks whether to install them. Click "Install" (see step 9).
A logged-in RuntimeNoKernelHub ships no model. It drives a CLI coding agent that you installed and logged into yourself (Claude Code by default). Installed is not usable: until you log in, tasks still cannot run.
A phoneWith the KernelHub app installed, for scanning the pairing code, sending tasks and approving.
Three rules (follow them in this order and you skip most of the redo)
  1. Install Node first, then KernelHub. The other way round, you end up unable to work (it is recoverable: once Node is in, run the install command again).
  2. Log the Runtime in once after installing (type claude and follow the prompts). Otherwise every task comes back with "no runtime here can run it".
  3. After pairing, keep icloser run open (or install it as a background agent). Pairing only introduces your phone to this Mac; the thing that actually picks up work is icloser run.
Where the "you will see" samples come from
The grey boxes are verbatim from a real run: on a macOS 27.0 (Apple silicon) machine, an empty home folder plus a PATH with only system folders stood in for a brand-new Mac. It differs from a truly new Mac in three places, each noted at its step: Xcode was already installed, so git showed no dialog; the background agent would collide with that machine's existing one, so it was not run; logging claude in touches the keychain, so it was not logged in there. User names, machine names and paths in the output have been replaced with examples.

How to open Terminal

Press Command + Space, type Terminal, press Enter. A window you can type into means you're in. No step on this page needs sudo.

2 · With internet access: the shortest path (15 steps)

One line per step, copy and run.

Step 1 · Check whether this Mac has Node

$ node -v

Node already installed: it prints a version (for example v24.21.0) — skip ahead to step 3; steps 4 and 5 can be skipped.

On a fresh Mac you will see (Node is missing; carry on):

zsh:1: command not found: node

Step 2 · Apple silicon or Intel? (just a look)

$ uname -m

arm64 means Apple silicon, x86_64 means Intel. The commands below pick the right files on their own; nothing to change.

Step 3 · Put ~/.local/bin on your PATH

This line does three things: appends one line to ~/.zshrc if it isn't there yet, applies it to the current window straight away, and prints the first PATH entry so you can see it. Running it twice doesn't add it twice.

$ grep -qsF ".local/bin" ~/.zshrc || echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc; export PATH="$HOME/.local/bin:$PATH"; echo "$PATH" | cut -d: -f1

Success: it prints /Users/your-name/.local/bin:

/Users/you/.local/bin

Step 4 · Download Node.js and check it against the official checksum

The current LTS is Node v24.21.0. This line downloads the official nodejs.org .tar.gz for your chip, then checks it against nodejs.org's official SHASUMS256.txt (about 50 MB, give it a moment):

$ V=v24.21.0; A=$(uname -m | sed "s/x86_64/x64/"); F=node-$V-darwin-$A.tar.gz; curl -fL -o /tmp/$F https://nodejs.org/dist/$V/$F && curl -fsSL https://nodejs.org/dist/$V/SHASUMS256.txt | grep " $F\$" | (cd /tmp && shasum -a 256 -c -)

Success: the last line is the file name followed by OK:

node-v24.21.0-darwin-arm64.tar.gz: OK

Ends in FAILED or did NOT match: the download is broken — run the line again. Errors like curl: (35) or (28): a network problem; retry, and if it keeps failing set a proxy (section 6).

node-v24.21.0-darwin-arm64.tar.gz: FAILED
shasum: WARNING: 1 computed checksum did NOT match

Step 5 · Unpack Node into ~/.local (no sudo)

$ V=v24.21.0; A=$(uname -m | sed "s/x86_64/x64/"); mkdir -p ~/.local && tar -xzf /tmp/node-$V-darwin-$A.tar.gz -C ~/.local --strip-components=1 && node -v && npm -v

Success: two version lines, one for node and one for npm:

v24.21.0
11.19.0

Why this way: node, npm, and later icloser and claude all end up in ~/.local/bin, and npm's global installs land in ~/.local too — no sudo anywhere, no EACCES errors. command not found: node: step 3 wasn't done; do it, then rerun this line.

Step 6 · Install KernelHub with one line

$ curl -fsSL https://icloser.xyz/install | sh

It does these things in order — you don't have to do anything, just watch:

What it doesDetails
Identifies the machineDetects macOS and the chip (arm64 / amd64).
Reads the release manifestFetches stable.json from kernelhub.icloser.xyz; refuses to install unless it says READY, with no override.
Downloads and verifiesDownloads icloser, checks SHA-256 and size, discards it and stops on mismatch.
Where it goes~/.local/bin/icloser, plus three legacy names icli / kernelhub-cli / devnexus-cli; it also clears the quarantine flag macOS puts on downloads.
Local consoleAlso installs ~/.local/bin/kernelhub-desktop; if that download fails it prints one warning and the CLI install still stands.
Self-checkRuns icloser version on the spot and compares it with the manifest's version and build.
One RuntimeIf npm is there: npm install -g @anthropic-ai/claude-code (only claude, by default). If it's already installed, it's left alone.

On success you'll see (the installer's messages are in Chinese):

  清单:stable 频道 · v1.0.2 · build 202609161352 · commit a4099c062543
下载 icloser_darwin_arm64 …
✓ SHA-256 核对通过
✓ 装到 /Users/you/.local/bin/icloser
✓ 装到 /Users/you/.local/bin/kernelhub-desktop(本机管理台)
✓ icloser 1.0.2 (build 202609161352, commit a4099c062543)
装 Runtime:claude(npm install -g @anthropic-ai/claude-code)…
✓ 装好 Runtime:claude(@anthropic-ai/claude-code)
下一步:
  ① 登录 Runtime(只用一次)。装上但没登录,任务照样跑不了:
        claude
     按提示登录完,退出它即可。
  ② cd 到你的项目目录,跑:
        icloser pair

If it contains "这台机器上没有 npm,Runtime 没装" (no npm on this machine, no Runtime installed), steps 4–5 were skipped or didn't take. KernelHub itself is installed; go back, install Node, then run this line again:

  清单:stable 频道 · v1.0.2 · build 202609161352 · commit a4099c062543
下载 icloser_darwin_arm64 …
✓ SHA-256 核对通过
✓ 装到 /Users/you/.local/bin/icloser
✓ 装到 /Users/you/.local/bin/kernelhub-desktop(本机管理台)
✓ icloser 1.0.2 (build 202609161352, commit a4099c062543)
  ⚠️ 这台机器上没有 npm,Runtime 没装(KernelHub 本体已经装好)
     装好 Node.js(自带 npm)之后重跑一次这个安装器即可。

If it says "管理台没下下来 —— 只装了 CLI" (console didn't download, CLI only): usually a network hiccup — just run the line again.

Step 7 · Check which version you got

$ icloser version

Success: one line containing both 1.0.2 and 202609161352:

icloser 1.0.2 (build 202609161352, commit a4099c062543)

command not found: icloser: step 3 wasn't done; do it and retry, or open a new Terminal window and retry.

Step 8 · Log the Runtime in once

First, see what it looks like before logging in. The first output is long (a matrix plus dozens of lines of notes) — only look at the Claude Code row at the top: before login it says 状态不明 (STARTABLE_AUTH_UNKNOWN), after login ✅ 可用 (AUTHENTICATED).

$ icloser runtimes
这台机器上的 Runtime(14 家已注册 · 1 家装着 · 0 家可直接用 · 0 家卡在登录/凭据)
     Runtime                版本          状态           登录态 / 位置
  ⚠️ Claude Code            问不出         状态不明         声明了探测手段但一条都没命中,状态问不出来(不猜)
  Claude Code            STARTABLE_AUTH_UNKNOWN       起得来,但登录态问不出来:声明了探测手段但一条都没命中,状态问不出来(不猜)

Then log in (the first run walks you through it, usually by opening a browser; once you reach the chat screen, type /exit or press Control + C twice to leave):

$ claude

Run icloser runtimes again. Success: the Claude Code row turns into ✅ 可用, with AUTHENTICATED in the six states.

This step was not run on the fresh-Mac setup behind this page (logging in touches the keychain); for the login screens and the after-login state of the same claude 2.1.272, see step 8 of Linux from zero.

Still stuck on login (the state reads STARTABLE_NOT_AUTHED or "unknown" (STARTABLE_AUTH_UNKNOWN)): type claude and log in again.

Step 9 · Create a project folder and go into it

Keep projects somewhere like ~/Projectsnot in Documents, Desktop or Downloads (see the pitfall in step 15). If you already have a project, use its path instead:

$ mkdir -p ~/Projects/my-app
$ cd ~/Projects/my-app

The first time something uses git (usually the next step's icloser pair, or when an AI employee starts working), macOS may pop up a dialog saying it needs the Command Line Developer Tools. Click Install, wait for it to finish (a few minutes), then run that command again.

This step was not run on the fresh-Mac setup behind this page (Xcode was already installed there, so no dialog appeared).

Step 10 · Pair your phone

$ icloser pair

It does three things in turn:

  1. Creates a workspace in the current folder.
  2. Asks how far the agent may go on this machine — just press Enter for tier 3, read + write + execute: it can change files and run builds and tests. Most people pick this.
  3. Draws a QR code in the window, with a "paste this if you can't scan" link below it.
  这台机器上,Agent 可以自己做到哪一步?(现在 6 档全是关的)

    1  只读                能看能想,不改文件
    2  读 + 写             多数人要的
    3  读 + 写 + 执行      开发 ← 能 build/test/装依赖/生成产物
    4  开发 + 联网         3 + 能上网查当前信息(只取不发)
    5  完整开发            4 + 还能推到远端(git push)
    6  完整开发 + 运维     5 + 能管这台机器的服务与部署(起停服务、docker/kubectl/helm/terraform 的写侧)

  选一个 [1/2/3/4/5/6],回车=3:设备 cli-your-mac.local 在工作区 7a9e5014-a076-40c7-a16b-a4b7e61ee88e 的自治边界:
  ✓ 这台机器:读文件 + 写入文件 + 执行脚本 / 命令(要改:icloser grant read write exec web push sysops)
  下一步只有一件事——让手机说的话有人接:

      icloser run

Scan the code with the KernelHub app on your phone.

QR code scrolled away? Do not run pair again. Pairing again creates a new, empty workspace, and none of your earlier tasks are in it. Bring the code back with:
$ icloser qr

Step 11 · Enter an invitation code in the phone app

The first time a brand-new account runs pair, the window shows this (verbatim from the Mac run):

  账户 7a9e5014 还没有使用权 —— 在 iPhone 或 Android 上输入一次邀请码即可,
  这台机器会自动继承(CLI 上没有激活入口)

It says, in Chinese: this account has no access yet — enter an invitation code once on iPhone or Android and this machine inherits it; the CLI has no activation entry. Open the KernelHub app on your phone and enter your invitation code there. Once it is redeemed, this computer inherits it automatically; nothing to type here.

How to get a code: Access & activation. An account that is already active says access was inherited during pair, and you skip this step.

Step 12 · Start taking work

$ icloser run

Leave this window open. It keeps running and checks for new tasks every few seconds — it is what picks up the tasks you send from your phone. Its first lines say which workspace it joined and which Runtime it chose:

icloser · 设备 cli-your-mac.local · 工作区 7a9e5014-a076-40c7-a16b-a4b7e61ee88e
Selected Runtime: claude · 适配器 claude-code(支持会话接续、只读可强制)
  选择原因: eligible pool 里最佳可用:claude
工作目录 /Users/you/Projects/my-app · 轮询 3s
等待命令中(Ctrl-C 退出)…

Step 13 · Send a real task and watch it deliver

With the step 12 window still open, pick up your phone:

  1. In the KernelHub app, choose the workspace you just paired and type one sentence into the box. Name the file if you know it, for example "Add a line with today's date at the end of README.md. Don't commit."
  2. The icloser run window on your computer scrolls a few new lines — the task has been picked up. On the phone the task card turns into a live view: which files it read, which commands it ran, which files it changed.
  3. If the task lacks a permission tier, it stops before acting and shows a card; approving applies to this task only.
  4. When it finishes, tap the card's changes to read the diff line by line, then read the result: what it did, what it changed, what it couldn't do. Not happy? Ask for changes, and the same task carries on.

Success: the task shows as done, the changes show the new line in README.md, and the file on your computer really has that extra line.

No Go / Python on a fresh machine? The first task does not stop for it
KernelHub checks the machine-level base tools (Go, Python) on the way. If one is missing and this machine has not been allowed to access the internet, the task carries on and no card is raised; the icloser run window just logs one line (verbatim from the CLI source, in Chinese: the base tool is not installed, no card, not blocking, the task carries on; to fill it in run icloser env bootstrap go, or allow exec + web for this device):
  ⓘ go:KernelHub Base(机器级,与这条任务无关)没装上 —— 不挂卡、不阻塞,这条任务照常往下跑。要补齐:在这台机器上跑 icloser env bootstrap go,或在设备权限里批 exec + web 后它会自动补上。
A card appears only when the task really needs it — the request names it (say, it mentions go build) or the work actually runs it — and the install is refused; approving applies to this one task only. On a machine that already allows exec and internet access it installs the tool and carries on without any card (seen on a real Windows machine).

Nobody picks it up: check that the step 12 window is still open; if it's still stuck, do the health check in the next step.

Step 14 · Health check (in a second Terminal window)

The step 12 window is busy, so press Command + N for another window and run:

$ icloser doctor

This step was not run on the fresh-Mac setup behind this page (see the Linux page for what the health check looks like).

It checks the service, gateway, queue, permissions and Runtimes in one go. Whatever is wrong, it tells you what to type next.

Step 15 · Keep working after you close the window: run it in the background

Once the step 12 window is closed, nobody picks up tasks from your phone. To have it start when you log in to the Mac and restart itself if it dies, run this (no sudo; it uses the project folder recorded at pairing, so it doesn't matter which folder you type it in):

$ icloser daemon install

This step was not run on the fresh-Mac setup behind this page (it would collide with that machine's existing background agent).

Check on it any time:

$ icloser daemon status

With the background agent installed, you can close the manual icloser run from step 12. On a Mac, icloser service install does the same thing — use one or the other.

The most common Mac background-agent pitfall: the project is in Documents, Desktop or Downloads
macOS privacy protection covers those three folders. When you run icloser run from Terminal, access goes through Terminal (the first time you may get a prompt — allow it). But the background agent is started by the system after you log in, with no window to show a prompt — so it gets stuck entering the project folder and never starts working, while icloser daemon status still says it's running. Tasks from your phone just sit there.
The easiest fix: keep projects out of those three folders (~/Projects from step 9 doesn't have this problem). Already in one and don't want to move it: skip the background agent and keep icloser run open in Terminal.
To check whether you're affected, type pwd in the project folder: if the path contains /Documents/, /Desktop/ or /Downloads/, you are.
$ pwd

3 · Local console

The console is a separate program; icloser run doesn't start it. Start it (this window stays busy too):

$ kernelhub-desktop --port 18092

Then open http://127.0.0.1:18092 in your browser. It listens only on the loopback address, so nothing outside this Mac can reach it. To see whether it's running and at what address:

$ icloser console

If it's running, this opens it in your default browser:

$ icloser open

4 · The other way: KernelHub Desktop, dragged into Applications

The download page has KernelHub-Desktop-1.0.2-macos-universal.dmg (one package for Apple silicon and Intel, signed and notarized by Apple). Open it and drag KernelHub Desktop into Applications.

We mounted this DMG and checked it item by item. Here's what's actually in it:

Bottom line: if you only want to click buttons, the DMG saves you the "install KernelHub" line; for Node and the login you still open Terminal once.

5 · Another way to get Node: the official .pkg installer

If you'd rather not type steps 4 and 5, you can download the macOS installer (.pkg) from nodejs.org and click Continue through it. It installs into system folders, and afterwards npm install -g often fails with EACCES (permission denied) — including the step where the KernelHub installer installs claude for you.

Don't force it with sudo. Point npm's global folder at ~/.local instead (do section 2, step 3 first):

$ npm config set prefix ~/.local && npm config get prefix

Success: it prints /Users/your-name/.local. Then run step 6's install command again.

6 · Adding Runtimes, blocked networks

Add another Runtime (no need to rerun the whole install)

Only claude is installed by default. These can be installed with npm: claude, codex, qwen, codebuddy, opencode, kimi, mimo, pi. This line installs codex; swap in any of them:

$ icloser env bootstrap codex

Or pick it through the installer (again, swap codex for the one you want):

$ KERNELHUB_RUNTIME=codex curl -fsSL https://icloser.xyz/install | sh

Each one needs its own login (type its name, for example codex). Google's entry is agy (Antigravity); it does not come from npm — install it from Google's official channel.

Set a proxy (for this window only)

Replace PORT with your own proxy's address and port; the last part checks it:

$ export https_proxy=http://127.0.0.1:PORT http_proxy=http://127.0.0.1:PORT; curl -sS -o /dev/null -w "install -> HTTP %{http_code}\n" https://icloser.xyz/install

Success: it prints install -> HTTP 200. If not, the proxy is wrong — don't go further yet. Once it works, run section 2's commands in this same window.

Use an npm mirror

$ npm config set registry https://registry.npmmirror.com && npm config get registry

It echoes the mirror address. registry.npmmirror.com is a common public mirror; to use another one, swap the address.

Point KernelHub's downloads at a mirror / skip the Runtime

For company networks with an internal mirror (it must mirror the official folder exactly; SHA-256 is still checked; the installer script itself still comes from icloser.xyz):

$ KERNELHUB_INSTALL_BASE=https://your-mirror.example.com/kernelhub curl -fsSL https://icloser.xyz/install | sh

Install no Runtime at all (CLI only):

$ KERNELHUB_SKIP_RUNTIME=1 curl -fsSL https://icloser.xyz/install | sh

7 · Verify the files yourself

$ shasum -a 256 ~/.local/bin/icloser ~/.local/bin/kernelhub-desktop

Compare the output with the table below, using the two rows for your chip:

FileBytesSHA-256
icloser_darwin_arm64 (Apple silicon)12,052,5605c65a239094a8d039cc880aff65093ecfdaadd48d63278362b89e87313a9b11e
kernelhub-desktop_darwin_arm647,940,400816c5b267d726bb646fdea8ebc61ce6b769fec164b607f07722b785e245ce95a
icloser_darwin_amd64 (Intel)12,994,176a393a4223d0c80ddd758a66eb34cc6b0ac957330c9654d85a895849db5de70c4
kernelhub-desktop_darwin_amd648,507,1207c0be4da9458db85100dc64d3791fabd53f8c73b60b186f9d0f0135087ae528c
node-v24.21.0-darwin-arm64.tar.gzbed7eea5325e1108f32ce5228ddd6a5f0f08a499ee42aa7442aea583702f6057
node-v24.21.0-darwin-x64.tar.gz1462cb3b3046b815cf8ea436d3da450ec1a9f11dac7e5a46b0ada5305d7e8097
KernelHub-Desktop-1.0.2-macos-universal.dmg17,841,735582554f659d44c37051b664416b0de423448607907c6d835486a1b3f1954c5e3

The KernelHub rows match the release manifest stable.json exactly; the two Node rows come from nodejs.org's SHASUMS256.txt. The installer has already checked these for you — this is for anyone who wants to see it with their own eyes.

8 · Common errors: symptom → cause → the one line to run

What you seeCauseWhat to do
command not found: nodeNode not installed, or step 3 skippedSection 2, steps 3–5
command not found: icloser~/.local/bin isn't on PATHSection 2, step 3, or open a new Terminal window
Installer says "这台机器上没有 npm,Runtime 没装"KernelHub was installed before NodeInstall Node, then run curl -fsSL https://icloser.xyz/install | sh again
npm install -g fails with EACCESNode came from the .pkg, so the global folder is a system folderSection 5: npm config set prefix ~/.local
Installer says "管理台没下下来 —— 只装了 CLI"Network hiccupRun the install command again
Node check says FAILEDBroken downloadRerun the step 4 line
curl: (35) / (28) / (7)Network blocked or flakyRetry; otherwise set a proxy (section 6)
A dialog asks to install the Command Line Developer ToolsFirst use of gitClick Install, then rerun the command
Tasks come back with "no runtime here can run it"Runtime not installed or not logged inType claude to log in, then check with icloser runtimes
Phone paired, but tasks just sit thereicloser run isn't open and no background agent is installedRun icloser run in the project folder, or icloser daemon install from step 15
Background agent installed, status says running, tasks still sit thereThe project is in Documents / Desktop / Downloads and the agent is stuckSee the pitfall in step 15; meanwhile keep icloser run open in Terminal
The QR code scrolled awayThe window scrolledType icloser qrdon't pair again
curl: (18) / (35) / (56), or "清单和服务器上的产物对不上了" (manifest and server disagree), or just a single curl: (35) … line and nothing elseThe network dropped mid-download (seen several times in our runs; the artifacts were fine)Run the same command again
In icloser runtimes, Claude Code's version column says 问不出 (could not tell)The first probe did not get the version yet (measured: the second run showed 2.1.272)Wait a few seconds and run icloser runtimes again

9 · Uninstall / clean up completely

① If you installed the background agent, remove it first:

$ icloser daemon uninstall

② See exactly what would be deleted (list only):

$ ls -d ~/.kernelhub ~/.kernelhub-gate ~/.kernelhub-protected 2>/dev/null

③ Delete the data folders. The three hold configuration and the task ledger, identity credentials, and the protected root; it's only clean once all three are gone. You'll have to pair again afterwards:

$ rm -rf ~/.kernelhub ~/.kernelhub-gate ~/.kernelhub-protected

④ Delete the programs:

$ rm -f ~/.local/bin/icloser ~/.local/bin/icli ~/.local/bin/kernelhub-cli ~/.local/bin/devnexus-cli ~/.local/bin/kernelhub-desktop

If you installed the DMG, drag KernelHub Desktop from Applications to the Trash. The PATH line in ~/.zshrc can stay (Node lives in that folder too). Node and the Runtimes are yours: the Node from this page lives under ~/.local — if you don't want it, delete ~/.local/bin/node, ~/.local/bin/npm, ~/.local/bin/npx and ~/.local/lib/node_modules.