Installer internals
OpenClaw ships three installer scripts, served from openclaw.ai.
| Script | Platform | What it does |
|---|---|---|
install.sh | macOS / Linux / WSL | Installs Node if needed, installs OpenClaw via npm (default) or git, and can run onboarding. |
install-cli.sh | macOS / Linux / WSL | Installs Node + OpenClaw into a local prefix (~/.openclaw). No root required. |
install.ps1 | Windows (PowerShell) | Installs Node if needed, installs OpenClaw via npm (default) or git, and can run onboarding. |
Quick commands
install.sh:
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install.sh | bash
```
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install.sh | bash -s -- --help
```
**install-cli.sh:**
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install-cli.sh | bash
```
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install-cli.sh | bash -s -- --help
```
**install.ps1:**
```powershell
iwr -useb https://openclaw.ai/install.ps1 | iex
```
```powershell
& ([scriptblock]::Create((iwr -useb https://openclaw.ai/install.ps1))) -Tag beta -NoOnboard -DryRun
```
> **📝 Note:**
>
> If install succeeds but `openclaw` is not found in a new terminal, see [Node.js troubleshooting](./install/node#troubleshooting.md).
---
## install.sh
> **💡 Tip:**
>
> Recommended for most interactive installs on macOS/Linux/WSL.
### Flow (install.sh)
**Step 1: Detect OS**
Supports macOS and Linux (including WSL). If macOS is detected, installs Homebrew if missing.
**Step 2: Ensure Node.js 22+**
Checks Node version and installs Node 22 if needed (Homebrew on macOS, NodeSource setup scripts on Linux apt/dnf/yum).
**Step 3: Ensure Git**
Installs Git if missing.
**Step 4: Install OpenClaw**
- `npm` method (default): global npm install
- `git` method: clone/update repo, install deps with pnpm, build, then install wrapper at `~/.local/bin/openclaw`
**Step 5: Post-install tasks**
- Runs `openclaw doctor --non-interactive` on upgrades and git installs (best effort)
- Attempts onboarding when appropriate (TTY available, onboarding not disabled, and bootstrap/config checks pass)
- Defaults `SHARP_IGNORE_GLOBAL_LIBVIPS=1`
### Source checkout detection
If run inside an OpenClaw checkout (`package.json` + `pnpm-workspace.yaml`), the script offers:
- use checkout (`git`), or
- use global install (`npm`)
If no TTY is available and no install method is set, it defaults to `npm` and warns.
The script exits with code `2` for invalid method selection or invalid `--install-method` values.
### Examples (install.sh)
**Default:**
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install.sh | bash
```
**Skip onboarding:**
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install.sh | bash -s -- --no-onboard
```
**Git install:**
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install.sh | bash -s -- --install-method git
```
**Dry run:**
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install.sh | bash -s -- --dry-run
```
<details>
<summary>Flags reference</summary>
| Flag | Description |
| ------------------------------- | ---------------------------------------------------------- |
| `--install-method npm\|git` | Choose install method (default: `npm`). Alias: `--method` |
| `--npm` | Shortcut for npm method |
| `--git` | Shortcut for git method. Alias: `--github` |
| `--version <version\|dist-tag>` | npm version or dist-tag (default: `latest`) |
| `--beta` | Use beta dist-tag if available, else fallback to `latest` |
| `--git-dir <path>` | Checkout directory (default: `~/openclaw`). Alias: `--dir` |
| `--no-git-update` | Skip `git pull` for existing checkout |
| `--no-prompt` | Disable prompts |
| `--no-onboard` | Skip onboarding |
| `--onboard` | Enable onboarding |
| `--dry-run` | Print actions without applying changes |
| `--verbose` | Enable debug output (`set -x`, npm notice-level logs) |
| `--help` | Show usage (`-h`) |
</details>
<details>
<summary>Environment variables reference</summary>
| Variable | Description |
| ------------------------------------------- | --------------------------------------------- |
| `OPENCLAW_INSTALL_METHOD=git\|npm` | Install method |
| `OPENCLAW_VERSION=latest\|next\|<semver>` | npm version or dist-tag |
| `OPENCLAW_BETA=0\|1` | Use beta if available |
| `OPENCLAW_GIT_DIR=<path>` | Checkout directory |
| `OPENCLAW_GIT_UPDATE=0\|1` | Toggle git updates |
| `OPENCLAW_NO_PROMPT=1` | Disable prompts |
| `OPENCLAW_NO_ONBOARD=1` | Skip onboarding |
| `OPENCLAW_DRY_RUN=1` | Dry run mode |
| `OPENCLAW_VERBOSE=1` | Debug mode |
| `OPENCLAW_NPM_LOGLEVEL=error\|warn\|notice` | npm log level |
| `SHARP_IGNORE_GLOBAL_LIBVIPS=0\|1` | Control sharp/libvips behavior (default: `1`) |
</details>
---
## install-cli.sh
> **ℹ️ Info:**
>
> Designed for environments where you want everything under a local prefix (default `~/.openclaw`) and no system Node dependency.
### Flow (install-cli.sh)
**Step 6: Install local Node runtime**
Downloads Node tarball (default `22.22.0`) to `<prefix>/tools/node-v<version>` and verifies SHA-256.
**Step 7: Ensure Git**
If Git is missing, attempts install via apt/dnf/yum on Linux or Homebrew on macOS.
**Step 8: Install OpenClaw under prefix**
Installs with npm using `--prefix <prefix>`, then writes wrapper to `<prefix>/bin/openclaw`.
### Examples (install-cli.sh)
**Default:**
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install-cli.sh | bash
```
**Custom prefix + version:**
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install-cli.sh | bash -s -- --prefix /opt/openclaw --version latest
```
**Automation JSON output:**
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install-cli.sh | bash -s -- --json --prefix /opt/openclaw
```
**Run onboarding:**
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install-cli.sh | bash -s -- --onboard
```
<details>
<summary>Flags reference</summary>
| Flag | Description |
| ---------------------- | ------------------------------------------------------------------------------- |
| `--prefix <path>` | Install prefix (default: `~/.openclaw`) |
| `--version <ver>` | OpenClaw version or dist-tag (default: `latest`) |
| `--node-version <ver>` | Node version (default: `22.22.0`) |
| `--json` | Emit NDJSON events |
| `--onboard` | Run `openclaw onboard` after install |
| `--no-onboard` | Skip onboarding (default) |
| `--set-npm-prefix` | On Linux, force npm prefix to `~/.npm-global` if current prefix is not writable |
| `--help` | Show usage (`-h`) |
</details>
<details>
<summary>Environment variables reference</summary>
| Variable | Description |
| ------------------------------------------- | --------------------------------------------------------------------------------- |
| `OPENCLAW_PREFIX=<path>` | Install prefix |
| `OPENCLAW_VERSION=<ver>` | OpenClaw version or dist-tag |
| `OPENCLAW_NODE_VERSION=<ver>` | Node version |
| `OPENCLAW_NO_ONBOARD=1` | Skip onboarding |
| `OPENCLAW_NPM_LOGLEVEL=error\|warn\|notice` | npm log level |
| `OPENCLAW_GIT_DIR=<path>` | Legacy cleanup lookup path (used when removing old `Peekaboo` submodule checkout) |
| `SHARP_IGNORE_GLOBAL_LIBVIPS=0\|1` | Control sharp/libvips behavior (default: `1`) |
</details>
---
## install.ps1
### Flow (install.ps1)
**Step 9: Ensure PowerShell + Windows environment**
Requires PowerShell 5+.
**Step 10: Ensure Node.js 22+**
If missing, attempts install via winget, then Chocolatey, then Scoop.
**Step 11: Install OpenClaw**
- `npm` method (default): global npm install using selected `-Tag`
- `git` method: clone/update repo, install/build with pnpm, and install wrapper at `%USERPROFILE%\.local\bin\openclaw.cmd`
**Step 12: Post-install tasks**
Adds needed bin directory to user PATH when possible, then runs `openclaw doctor --non-interactive` on upgrades and git installs (best effort).
### Examples (install.ps1)
**Default:**
```powershell
iwr -useb https://openclaw.ai/install.ps1 | iex
```
**Git install:**
```powershell
& ([scriptblock]::Create((iwr -useb https://openclaw.ai/install.ps1))) -InstallMethod git
```
**Custom git directory:**
```powershell
& ([scriptblock]::Create((iwr -useb https://openclaw.ai/install.ps1))) -InstallMethod git -GitDir "C:\openclaw"
```
**Dry run:**
```powershell
& ([scriptblock]::Create((iwr -useb https://openclaw.ai/install.ps1))) -DryRun
```
**Debug trace:**
```powershell
# install.ps1 has no dedicated -Verbose flag yet.
Set-PSDebug -Trace 1
& ([scriptblock]::Create((iwr -useb https://openclaw.ai/install.ps1))) -NoOnboard
Set-PSDebug -Trace 0
```
<details>
<summary>Flags reference</summary>
| Flag | Description |
| ------------------------- | ------------------------------------------------------ |
| `-InstallMethod npm\|git` | Install method (default: `npm`) |
| `-Tag <tag>` | npm dist-tag (default: `latest`) |
| `-GitDir <path>` | Checkout directory (default: `%USERPROFILE%\openclaw`) |
| `-NoOnboard` | Skip onboarding |
| `-NoGitUpdate` | Skip `git pull` |
| `-DryRun` | Print actions only |
</details>
<details>
<summary>Environment variables reference</summary>
| Variable | Description |
| ---------------------------------- | ------------------ |
| `OPENCLAW_INSTALL_METHOD=git\|npm` | Install method |
| `OPENCLAW_GIT_DIR=<path>` | Checkout directory |
| `OPENCLAW_NO_ONBOARD=1` | Skip onboarding |
| `OPENCLAW_GIT_UPDATE=0` | Disable git pull |
| `OPENCLAW_DRY_RUN=1` | Dry run mode |
</details>
> **📝 Note:**
>
> If `-InstallMethod git` is used and Git is missing, the script exits and prints the Git for Windows link.
---
## CI and automation
Use non-interactive flags/env vars for predictable runs.
**install.sh (non-interactive npm):**
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install.sh | bash -s -- --no-prompt --no-onboard
```
**install.sh (non-interactive git):**
```bash
OPENCLAW_INSTALL_METHOD=git OPENCLAW_NO_PROMPT=1 \
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install.sh | bash
```
**install-cli.sh (JSON):**
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install-cli.sh | bash -s -- --json --prefix /opt/openclaw
```
**install.ps1 (skip onboarding):**
```powershell
& ([scriptblock]::Create((iwr -useb https://openclaw.ai/install.ps1))) -NoOnboard
```
---
## Troubleshooting
<details>
<summary>Why is Git required?</summary>
Git is required for `git` install method. For `npm` installs, Git is still checked/installed to avoid `spawn git ENOENT` failures when dependencies use git URLs.
</details>
<details>
<summary>Why does npm hit EACCES on Linux?</summary>
Some Linux setups point npm global prefix to root-owned paths. `install.sh` can switch prefix to `~/.npm-global` and append PATH exports to shell rc files (when those files exist).
</details>
<details>
<summary>sharp/libvips issues</summary>
The scripts default `SHARP_IGNORE_GLOBAL_LIBVIPS=1` to avoid sharp building against system libvips. To override:
```bash
SHARP_IGNORE_GLOBAL_LIBVIPS=0 curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install.sh | bash
```
</details>
<details>
<summary>Windows: </summary>
Install Git for Windows, reopen PowerShell, rerun installer.
</details>
<details>
<summary>Windows: </summary>
Run `npm config get prefix`, append `\bin`, add that directory to user PATH, then reopen PowerShell.
</details>
<details>
<summary>Windows: how to get verbose installer output</summary>
`install.ps1` does not currently expose a `-Verbose` switch.
Use PowerShell tracing for script-level diagnostics:
```powershell
Set-PSDebug -Trace 1
& ([scriptblock]::Create((iwr -useb https://openclaw.ai/install.ps1))) -NoOnboard
Set-PSDebug -Trace 0
```
</details>
<details>
<summary>openclaw not found after install</summary>
Usually a PATH issue. See [Node.js troubleshooting](./install/node#troubleshooting.md).
</details>