# Installing HarnessLink

HarnessLink is the controller for your coding agents — it routes their model calls, gives them shared memory, banks what they do, and syncs and restores your setup. You code in omp, Claude Code, Codex or pi. HarnessLink was called SuperPi until October 2026; the command is still `superpi` (see RENAME.md).

This guide covers a completely fresh machine through to the HarnessLink service running with your harnesses wired into it.

## What you actually need

| Requirement | Why | Auto-installed? |
| --- | --- | --- |
| **macOS, Linux, or Windows 10+** | Supported platforms | — |
| **Bun ≥ 1.3.14** | The CLI runs on Bun, not Node | yes (bun.sh) |
| A harness to code in | HarnessLink runs no model itself; model credentials stay with each harness | omp is installed for you (`--no-omp` skips it); it signs in on first run |

No GitHub account, token or `git` is needed, and nothing is compiled: the installer fetches the source tarball from harnesslink.sh and installs its production dependencies with Bun.

**Alpine (musl).** The installer adds bun's `libstdc++` and `libgcc` via apk. The npm omp package ships only glibc natives, so on musl omp comes from the upstream `omp-linux-musl-<arch>` release binary instead, checked against the release's `SHA256SUMS.txt`. `omp update` keeps using the musl asset.

The installer also installs **omp** (`@oh-my-pi/pi-coding-agent`, upstream oh-my-pi) — a harness to code in — and links it beside `superpi`. Pass `--no-omp` to skip that; Claude Code, Codex and pi work just as well.

## Windows

```powershell
irm https://harnesslink.sh/install.ps1 | iex
```

The PowerShell one-liner downloads and runs `install.ps1` from harnesslink.sh. Open PowerShell and paste it.

**Prerequisites**

| Requirement | Why | Auto-installed? |
| --- | --- | --- |
| **Windows 10+** | `tar.exe` ships with Windows 10; PowerShell 5.1 always present | — |
| **Bun ≥ 1.3.14** | The CLI runs on Bun, not Node | yes (`irm bun.sh/install.ps1 \| iex`) |
| A harness to code in | HarnessLink runs no model itself | omp is installed for you (`-NoOmp` skips it) |

The installer downloads the source tarball from `https://harnesslink.sh/superpi-src.tar.gz`, extracts it with the `tar.exe` that ships with Windows 10+ and installs its production dependencies with Bun. No git, GitHub or compiler involved.

**Installer parameters.** `irm … | iex` cannot pass parameters. To pass them, download the script and run it as a file:

```powershell
irm https://harnesslink.sh/install.ps1 -OutFile install.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File .\install.ps1 -Yes
```

| Parameter | Effect |
| --- | --- |
| `-DryRun` | Print what it would do; change nothing; exit 0 |
| `-NoOmp` | Skip installing omp |
| `-Yes` | Unattended: skip the onboarding and print `Finish setup: superpi cloud setup` instead |

There is no `--with` or `--cloud` equivalent on Windows. Install other harnesses afterwards with `superpi harness install <id>`, and run `superpi cloud setup` yourself after a `-Yes` install.

**Troubleshooting — Windows**

**`irm` blocked by execution policy** The default Windows policy may block running scripts downloaded from the internet. Bypass it for the current shell only (it is not a system-wide change):

```powershell
Set-ExecutionPolicy -Scope Process Bypass
irm https://harnesslink.sh/install.ps1 | iex
```

**`superpi: command not found` / `superpi.cmd` not recognised** Bun's bin directory (`%USERPROFILE%\.bun\bin`) is not on `PATH`. Add it permanently in **System Settings → Environment Variables**, or for the current session:

```powershell
$env:PATH = "$env:USERPROFILE\.bun\bin;$env:PATH"
```

**Bun install fails behind a proxy** Set `HTTPS_PROXY` before running the installer:

```powershell
$env:HTTPS_PROXY = 'http://proxy.corp.example.com:8080'
irm https://harnesslink.sh/install.ps1 | iex
```

**Environment variables for custom installs**

```powershell
$env:SUPERPI_DIR  = 'D:\dev\superpi-src'   # where to put the source
$env:SUPERPI_SITE = 'https://harnesslink.sh'  # tarball + installer base URL
irm https://harnesslink.sh/install.ps1 | iex
```

## Install

```bash
curl -fsSL https://harnesslink.sh/install.sh | bash
```

harnesslink.sh serves the repository's `install.sh` verbatim; it is the only source and needs no authentication.

From 17.5.55 the installer (and `superpi update`) also links `harnesslink` and `hlk` to the same command; `hlk` is skipped if another program already owns that name. All three behave identically, and this guide uses `superpi`. On Windows they are `superpi.cmd`, `harnesslink.cmd` and `hlk.cmd`.

### Options

```bash
bash install.sh --help

  --dir <path>     Source location (default: ~/.superpi-src)
  --no-omp         Skip installing omp (a harness to code in)
  --with=<ids>     Also install the listed harnesses after omp (comma-separated)
                     Valid ids: omp claude-code codex gemini pi dsh
                     Example: --with=claude-code,codex
  --cloud          Run the onboarding even with --yes (it still needs a
                     terminal: sign-in happens in your browser)
  --yes            Assume yes for anything that modifies the system
```

The installer is **re-runnable**: every step checks before acting, so running it again updates rather than reinstalls.

### Manual install

If you would rather see each step:

```bash
mkdir -p ~/.superpi-src && curl -fsSL https://harnesslink.sh/superpi-src.tar.gz | tar -xz -C ~/.superpi-src
cd ~/.superpi-src
bun install --production
sh scripts/link-superpi.sh    # links superpi (plus harnesslink and hlk) into ~/.bun/bin
bun install -g @oh-my-pi/pi-coding-agent   # omp, a harness to code in
```

## Verify

```bash
superpi --version
superpi --smoke-test
superpi                       # the home screen: service, sign-in, sync, each harness's wiring
```

`--smoke-test` loads every command and exercises the gateway and the MCP relay end to end in a throwaway directory, so a broken install fails here rather than on first use.

## First run — the onboarding

An interactive install ends by opening `superpi cloud setup` directly (no extra question: its first screen is the confirmation). `--yes`, CI and other headless runs skip it and print `Finish setup: superpi cloud setup` instead. Run it any time:

```bash
superpi cloud setup       # the onboarding: plan → sign in → everything else automatic
superpi cloud status      # sync health afterwards
superpi gateway status    # gateway + cloud sync health
```

1. **Plan.** One screen lists everything that turns on — all of it on by
   default: sign in, cloud sync, the HarnessLink service, then each harness found on this machine with the features it supports here, then restoring from the cloud (sessions, history, memories, harness setup) and importing old memories. Per-harness features and where each applies:
   | Feature | What it does | Harnesses |
   | --- | --- | --- |
   | Gateway routing | model calls go through the local gateway | Claude Code, Codex, omp, pi |
   | Transcript sync | session transcripts, prompt history and the harness's own memory files upload | every harness with an adapter: Claude Code, Codex, omp, pi, Cursor, Antigravity (see MULTI_HARNESS.md for what each one actually yields) |
   | Autobank | every finished turn becomes a memory bank entry, starting with the last 30 days; todo and plan snapshots too (see MEMORY_BANKING.md) | omp, pi, Claude Code, Codex, Antigravity — not Cursor |
   | Context hooks | project brief, matching memories and your org's policy instructions injected before the model answers; org tool and command rules checked before every tool call | Claude Code, Codex, omp |
   | Memory tools (MCP) | `superpi mcp` registered so the model can call memory tools | omp, Claude Code, Codex |
   A feature only appears when the harness is detected (its binary on `PATH`, or its data directory present). A **What syncs** block lists every sync category (prompt history from every harness, session transcripts, memories, usage from HarnessLink's old built-in agent, gateway usage, device profile), all ✓. **Enter** sets it all up, **c** customizes (toggle any sync category, harness or feature, including restore), **q** quits.
2. **Sign in.** A HarnessLink Cloud account is required. The device code is shown
   large, the browser opens on the approval page (**o** reopens it, **c** copies the code), and a spinner waits for your approval. Already signed in? It shows the account and moves on. Cancelling (**Esc**) or failing stops with "Setup is not complete: a HarnessLink Cloud account is required — run `superpi cloud setup` again" and exit code 1.
3. **Everything else runs by itself** on a live checklist (spinner → ✓ or ✗
   with a one-line detail): cloud sync on, with your sync category choices → the HarnessLink service (launchd on macOS, a `systemd --user` unit on Linux, a logon task on Windows) → per harness: gateway routing, transcript sync, autobank, context hooks (see USAGE.md), memory tools → restore (additive: never overwrites a local file): sessions, prompt history, memories, harness setup (agents, commands, skills, rules), old memories (MemPalace, Hermes) → verify (the gateway answers and is signed in, one prompt-history pass over every harness, the memory bank from every harness, a real sync round trip, sync health). A failed step does not stop the ones after it. The HarnessLink service notices harnesses turned on after it started; it does not need a restart.
4. **Summary.** ✓/✗ per step with the retry command for each failure, what
   is on now, and the standalone command for every piece.

Every piece stays a command of its own for manual setups:

| Piece | Command | Undo |
| --- | --- | --- |
| Sign in (required) | `superpi cloud login` | `superpi cloud logout` |
| Cloud sync (on whenever signed in) | `superpi cloud sync` | `cloud.sync: false` in config.yml, or `SUPERPI_CLOUD_SYNC=0` |
| What syncs (every category on by default) | `superpi cloud sync --enable <category>` | `superpi cloud sync --disable <category>` |
| HarnessLink service | `superpi gateway start` | `superpi gateway service uninstall` |
| Gateway routing | `superpi gateway connect [id]` | `superpi gateway disconnect [id]` |
| Transcript sync | `superpi cloud harnesses enable <id>` | `superpi cloud harnesses disable <id>` |
| Autobank | `superpi cloud autobank enable <id>` | `superpi cloud autobank disable <id>` |
| Context hooks | `superpi harness context [id]` | `superpi harness context [id] --remove` |
| Memory tools (MCP) | `superpi mcp register --harness=<id> --yes` |  |
| Restore | `superpi cloud pull-sessions --all` · `superpi cloud pull-history` · `superpi cloud pull-memories --all` · `superpi cloud restore --apply` |  |
| Import old memories | `superpi cloud import-memories --apply` |  |
| Check it all | `superpi gateway status` · `superpi cloud status` · `superpi cloud autobank status` |  |

Without a terminal, `superpi cloud setup` prints this list and exits 1.

The hosted service at [harnesslink.sh](https://harnesslink.sh) is the default. To run against your own Cloudflare stack instead, set it up first — see CLOUD_SETUP.md.

The dashboard's **Setup** page shows an eight-step checklist and ticks each step off from your real cloud data; the public copy lives at [harnesslink.sh/docs#connect-the-cloud](https://harnesslink.sh/docs#connect-the-cloud). The canonical definitions are code, not prose: `cloud/web/src/lib/setupSteps.ts` — update that file and this table together.

| # | Step | Command | Optional |
| --- | --- | --- | --- |
| 1 | Install and sign in — the installer puts HarnessLink and omp on the machine and opens `superpi cloud setup`, which turns on cloud sync, the service and, per harness found, gateway routing, transcript sync, autobank, context hooks and memory tools | `curl -fsSL https://harnesslink.sh/install.sh \| bash` |  |
| 2 | Cloud sync on — signing in turns it on; plain `superpi` shows sync health on its home screen | `superpi cloud status` |  |
| 3 | First sync completed — prompt in any connected harness (omp, Claude Code, Codex, pi, Antigravity) | `superpi cloud sync` |  |
| 4 | Profile pushed — the service uploads it by itself and whenever it changes (HarnessLink's config and MCP server names, plus each harness's agents, commands, rules, skills; never secret values); this refreshes it now | `superpi cloud push-profile` |  |
| 5 | Code intelligence wired | `curl -fsSL https://get.gortex.dev \| sh` | ✓ |
| 6 | HarnessLink skills folder in the profile — skills and agents the old built-in agent left in HarnessLink's own folder (`~/.superpi/agent`) travel inside the profile so a new machine can restore them (skills `superpi add` installs live in the harnesses' own skill folders; the Claude Code, omp and pi copies travel with that harness's setup); the dry run lists every file it carries | `superpi cloud push-profile --dry-run` | ✓ |
| 7 | Memories in the cloud — each harness's memory files and memory bank upload by themselves; setup imports older MemPalace and `~/.hermes` memories once | `superpi cloud import-memories --apply` | ✓ |
| 8 | Adopt on another machine — `config.yml` backed up before it is replaced, harness files only created, MCP servers disabled until approved | `superpi cloud restore --device <device-id> --apply --install-tools` | ✓ |

## Updating

```bash
superpi update
```

A picker over every harness on the machine — omp first, then HarnessLink itself, then Claude Code, Codex and others that are installed — running each one's own updater. HarnessLink updates itself by re-running the installer from harnesslink.sh. Non-interactive runs update HarnessLink directly.

**Old-agent leftovers.** HarnessLink's old built-in agent left git worktrees in `~/.superpi/wt` (they can reach many GB) and the output of its background jobs in `~/.superpi/run/daemons` (logs only, often hundreds of MB). `superpi update` and the `superpi` home screen offer to remove them, showing their combined size; `superpi cleanup` does it on demand. Nothing is deleted without your yes, and worktrees with uncommitted changes are listed and never deleted without saying so.

**An update tidies after itself.** Re-running the installer over `~/.superpi-src`:

- removes whatever the previous version shipped that this one does not: whole
  directories (the old built-in agent, the native addon and their build outputs) and single files alike — a plain extract only adds and overwrites;
- rebuilds `node_modules` from scratch when the set of packages changed, so
  the old tree's dependencies (1.4 GB before HarnessLink became a controller) do not linger, and says how much space it freed;
- removes a `.git` left by a pre-cutover clone, so `superpi update` never
  turns into a private-repository credential prompt;
- keeps build products of what it still ships (`node_modules`, `dist`,
  generated sources) and dotfiles at the root of the tree. A bazel cache an old native build left elsewhere is named, never deleted.

The installer refuses to install over a git checkout at a custom `--dir`, or over any non-empty directory that is not already a HarnessLink install — it would otherwise overwrite and prune your files.

## Troubleshooting

**`superpi: command not found`** `~/.bun/bin` is not on your `PATH`. Add it and open a new shell:

```bash
export PATH="$HOME/.bun/bin:$PATH"
```

**`superpi` says you are not signed in, or shows an empty setup** Check which config directory is in use — a stray `SUPERPI_CONFIG_DIR` (or, from 17.5.55, `HARNESSLINK_CONFIG_DIR`) in your environment will point the CLI at an empty profile:

```bash
echo "$HARNESSLINK_CONFIG_DIR $SUPERPI_CONFIG_DIR"    # expect both empty
```

Both names work; when both are set, `HARNESSLINK_CONFIG_DIR` wins. `SUPERPI_CONFIG_DIR` accepts either a **relative name** (resolved under `$HOME`, default `.superpi`) or an **absolute path** (used as-is as the full config root). A relative name such as `cfg` resolves to `$HOME/cfg`; an absolute path such as `SUPERPI_CONFIG_DIR=/tmp/cfg` uses `/tmp/cfg` directly. To run against a different profile, set `SUPERPI_CONFIG_DIR` to an absolute path, or set `HOME` to redirect all relative resolution.

## Uninstalling

Undo the wiring **before** deleting anything. The harnesses' own configs point at HarnessLink (gateway base URLs, hooks, MCP entries); deleting the `superpi` binary first leaves them pointing at nothing, and connected harnesses then fail with "connection refused".

```bash
superpi gateway disconnect              # put back each harness's own provider settings
superpi harness context --remove        # remove HarnessLink's context hooks (Claude Code, Codex, omp)
superpi gateway service uninstall       # stop and remove the LaunchAgent / systemd unit / logon task
superpi cloud logout                    # optional: unlink this machine from your account
superpi add --list                      # optional: registry add-ons HarnessLink put in harness skill folders
superpi remove <name>                   #   remove each one (only the files HarnessLink wrote)
```

Then remove HarnessLink's MCP entry from each harness you registered it in:

| Harness | How |
| --- | --- |
| Claude Code | `claude mcp remove --scope user superpi` |
| Codex | delete the `[mcp_servers.superpi]` block from `~/.codex/config.toml` |
| omp | delete `mcpServers.superpi` from `~/.omp/agent/mcp.json` |
| Cursor | delete `mcpServers.superpi` from `~/.cursor/mcp.json` |

Finally remove HarnessLink itself:

```bash
rm -f ~/.bun/bin/superpi
rm -rf ~/.superpi-src
rm -rf ~/.superpi          # ⚠️ also deletes local history, memory and sessions
```

On Windows, delete `%USERPROFILE%\.bun\bin\superpi.cmd` and `%USERPROFILE%\.superpi-src` instead.

This leaves omp, pi, Claude Code, Codex and every other harness installed — they are separate programs. In particular, `~/.bun/bin/pi` is the pi harness, not part of HarnessLink. Remove a harness with its own uninstaller if you want it gone.
