# Installation

> macOS Apple Silicon prerequisites, Node 26.5.x, Git LFS, Xcode tools, optional Docker, and npm ci.

- Repository: sashimikun/grok-bot-0.18-reconstructed
- GitHub: https://github.com/sashimikun/grok-bot-0.18-reconstructed
- Human docs: https://grok-wiki.com/public/docs/sashimikun-grok-bot-0-18-reconstructed-c774cc9a5c15
- Complete Markdown: https://grok-wiki.com/public/docs/sashimikun-grok-bot-0-18-reconstructed-c774cc9a5c15/llms-full.txt

## Source Files

- `package.json`
- `README.md`
- `scripts/lib/system-tools.mjs`
- `scripts/lib/config.mjs`
- `research-archives/README.md`
- `scripts/apply-third-party-patches.mjs`

---

---
title: "Installation"
description: "macOS Apple Silicon prerequisites, Node 26.5.x, Git LFS, Xcode tools, optional Docker, and npm ci."
---

The reconstruction is a Node workspace that installs with `npm ci` from `package-lock.json` (`lockfileVersion` 3) and then hydrates a checksum-pinned 0.18.0 macOS arm64 Electron shell. `package.json` names the package `grok-bot-0.18-reconstructed` at `0.18.0-reconstructed.1`, sets `"type": "module"`, and constrains `engines.node` to `>=26.5.0 <27`. `npm ci` also runs `postinstall` (`node scripts/apply-third-party-patches.mjs`). Packaging (`scripts/package-macos.mjs`) throws if `process.platform !== "darwin"`. The pinned DMG is the Git LFS object `research-archives/original/0.18.0/macos-arm64/Grok_Bot_0.18.0.dmg` (SHA-256 `a253ccd8aab01e083f9812a0264354c5034d8ba7f0610bbb557e82ae77d203eb`).

<Warning>
Do not treat this checkout as a cross-platform app factory. The Windows x64 installer is preserved for research identity only. `npm run package` and `npm run smoke` require Darwin; the official shell is a thin arm64 Mach-O (`0xfeedfacf`).
</Warning>

## Supported host

| Constraint | Value | Enforced by |
| --- | --- | --- |
| OS | macOS (`darwin`) | `scripts/package-macos.mjs`, `scripts/package-fidelity-diagnostic.mjs` |
| CPU | Apple Silicon (`arm64`) | Pinned DMG `darwin-arm64/0.18.0`; Mach-O parser in `scripts/lib/macos-shell-invariant.mjs` |
| Node | `>=26.5.0 <27` | `package.json` `engines.node` |
| Package manager | `npm ci` against the committed lockfile | `package-lock.json`, `CONTRIBUTING.md` |
| Bundle identity after package | `com.anysphere.sand.reconstructed` | `scripts/lib/config.mjs` `reconstructedBundleId` |
| Default output app | `dist/Grok Bot 0.18 Reconstructed.app` | `GROK_BOT_OUTPUT_APP_NAME` override, else `reconstructedName` |

`src/app/package.json` still reports upstream product `sand` / `Grok Bot` `0.18.0`. That file is the hydrated app manifest, not the reconstruction workspace identity.

## Prerequisites

| Tool | Required for | Notes |
| --- | --- | --- |
| Node.js 26.5.x (any `26.5.0`–`<27`) | `npm ci`, tests, TypeScript, scripts | README documents 26.5.x; `engines` is the hard range |
| Git LFS | `research-archives/original/**/*.dmg` and `*.exe` | `.gitattributes` `filter=lfs` |
| Xcode Command Line Tools | bootstrap attach, ad-hoc sign, `plutil`, `node-gyp` | Absolute tool paths in `scripts/lib/system-tools.mjs` |
| Docker CLI + a running daemon | optional local box (`local-docker`) | Default box runtime stays `remote` |
| Cursor / Claude Code / Codex / OpenRouter auth | routed inference after launch | Not part of `npm ci` |

<Note>
Provider sessions are runtime credentials, not install-time packages. Cursor is the default inference provider. Claude Code and Codex reuse existing local logins; OpenRouter needs `OPENROUTER_API_KEY` later.
</Note>

## Install Node 26.5.x

Confirm the host interpreter before `npm ci`:

```sh
node -v
# expected: v26.5.x  (engines: >=26.5.0 <27)
```

`@types/node` is pinned at `26.2.0`. Electron `42.1.0` is a `devDependency` (headers/ABI 146, Electron Node `24.15.0` for native rebuilds). Host Node 26 and the Electron runtime Node 24 are different processes; do not swap the workspace interpreter to 24 to match Electron.

## Xcode Command Line Tools

Bootstrap, package, and verify spawn Apple binaries by absolute path (`shell: false` in `scripts/lib/process.mjs`). Those binaries come from Xcode Command Line Tools:

| Constant | Path | Used for |
| --- | --- | --- |
| `hdiutil` | `/usr/bin/hdiutil` | Attach/detach the 0.18.0 DMG during `npm run bootstrap` |
| `ditto` | `/usr/bin/ditto` | Copy `Grok Bot.app` into `.cache/runtime/` and `dist/` |
| `plutil` | `/usr/bin/plutil` | Read/write `Info.plist` (`CFBundleIdentifier`, URL types, version) |
| `codesign` | `/usr/bin/codesign` | Ad-hoc sign (`--sign -`) and `--verify --deep --strict` |
| `xattr` | `/usr/bin/xattr` | `xattr -cr` on the reconstructed `.app` (clear quarantine) |
| `cp` / `lsof` / `ps` | `/bin/cp`, `/usr/sbin/lsof`, `/bin/ps` | Copy and native smoke/process inspection |

`node-gyp@12.1.0` and `node-addon-api@8.5.0` are workspace `devDependencies`. `postinstall` rewrites `node_modules/tree-sitter/binding.gyp` so Node ≥ 22 uses C++20 (`cxxstd`). Packaging stages tree-sitter via `scripts/build-tree-sitter-node.mjs`. Missing CLT shows up as `hdiutil`/`codesign`/`node-gyp` spawn failures, not as a custom Node error.

If `/usr/bin/hdiutil` or `/usr/bin/codesign` is missing:

```sh
xcode-select --install
xcode-select -p
```

## Git LFS

`.gitattributes` tracks:

```text
research-archives/original/**/*.dmg filter=lfs diff=lfs merge=lfs -text
research-archives/original/**/*.exe filter=lfs diff=lfs merge=lfs -text
```

`artifacts.json` (`schemaVersion` 1) is the size/digest inventory. A pointer-sized file fails `tests/research-archives.test.mjs` with `requires git lfs pull` because `lstat` size must equal `artifact.bytes`.

| Artifact | Bytes | SHA-256 |
| --- | ---: | --- |
| `macos-arm64/Grok_Bot_0.18.0.dmg` | 155793020 | `a253ccd8aab01e083f9812a0264354c5034d8ba7f0610bbb557e82ae77d203eb` |
| `windows-x64/Grok_Bot_0.18.0_Setup.exe` | 125825552 | `464079a15ef5fa8b61ccea8fffcc78f63cfcf6df65fb0ad5e725d8b95f7e437e` |

If the archived DMG is present but the digest is wrong, `scripts/bootstrap-runtime.mjs` throws `Archived DMG checksum mismatch … Run git lfs pull before bootstrapping.`

## npm ci

`npm ci` is the supported install. It materializes `node_modules/` from `package-lock.json` and sets `hasInstallScript: true`.

`postinstall` / `npm run native:patch` patches only stock SHA-256 inputs:

| Target | Purpose |
| --- | --- |
| `@connectrpc/connect` ESM + CJS `protocol-connect/transport.js` | Set `Content-Length: 0` on empty request bodies |
| `tree-sitter/binding.gyp` | Select C++17 vs C++20 from `npm_config_target` / `process.versions.node` |

Unexpected bytes abort: `Refusing to patch unexpected @connectrpc/connect input …`. Already-patched files are skipped (`patchedSha256`).

Generated trees stay out of Git (`.gitignore`): `node_modules/`, `.cache/`, `.build/`, `dist/`, `src/app/dist/`, `recovered/`.

:::files
repo/
  package.json                 # engines.node >=26.5.0 <27; postinstall
  package-lock.json            # lockfileVersion 3; npm ci input
  scripts/apply-third-party-patches.mjs
  scripts/lib/system-tools.mjs
  scripts/lib/config.mjs
  research-archives/original/0.18.0/
    artifacts.json
    SHA256SUMS
    macos-arm64/Grok_Bot_0.18.0.dmg   # Git LFS
    windows-x64/Grok_Bot_0.18.0_Setup.exe
  src/app/                     # package.json checked in; dist/ ignored until bootstrap
  node_modules/                # created by npm ci
  .cache/runtime/Grok Bot.app  # created by bootstrap
  dist/                        # created by package
:::

## Optional Docker

Local sandbox is not an install gate. `source/electron-main/box/local-docker-host-connector.ts` shells out to `docker` and probes `docker info`. Constants:

| Name | Value |
| --- | --- |
| `LOCAL_DOCKER_BOX_IMAGE` | `public.ecr.aws/k0i0n2g5/cursorenvironments/universal:sand-box-latest` |
| `LOCAL_DOCKER_BOX_CONTAINER` | `grok-bot-local-vm` |
| `LOCAL_DOCKER_GATEWAY_URL` | `http://127.0.0.1:1340` |
| `LOCAL_DOCKER_OWNER_LABEL` | `com.grok-bot.local-vm=1` |
| `LOCAL_DOCKER_SCHEMA_VERSION` | `6` |

If the daemon is down, status is `available: false` with detail `Docker is not running.` or the `docker` spawn error. Default box mode remains `remote`.

## Install the workspace

<Steps>
<Step title="Clone and enable LFS">

```sh
git clone <your-repository-url>
cd grok-bot-0.18-reconstructed
git lfs install
git lfs pull
```

</Step>
<Step title="Confirm Node and Apple tools">

```sh
node -v
uname -m
test -x /usr/bin/hdiutil && test -x /usr/bin/codesign && echo ok
```

`uname -m` must be `arm64`. `node -v` must satisfy `>=26.5.0 <27`.

</Step>
<Step title="Install lockfile dependencies">

```sh
npm ci
```

Expect `postinstall` to finish without patch-drift errors. Do not use a floating `npm install` as the documented contributor path.

</Step>
<Step title="Verify LFS payloads">

```sh
(cd research-archives/original/0.18.0 && shasum -a 256 -c SHA256SUMS)
```

Both lines must print `OK`. Optional: `git lfs ls-files` should list both installers.

</Step>
</Steps>

<ParamField body="GROK_BOT_018_APP" type="string">
Optional absolute path to an already-extracted `Grok Bot.app`. When set, bootstrap copies that app with `ditto` instead of attaching the DMG. `CFBundleShortVersionString` must be `0.18.0`.
</ParamField>

<ParamField body="GROK_BOT_OUTPUT_APP_NAME" type="string">
Optional basename for the packaged app under `dist/`. Default is `Grok Bot 0.18 Reconstructed.app`.
</ParamField>

Installation stops at a complete `node_modules/` plus real LFS binaries. Hydrating `src/app/dist` is `npm run bootstrap`. Compiling runtimes and writing the `.app` is `npm run package`.

## Verification

<Check>
A successful install has Node in range, `npm ci` exit 0, Connect/tree-sitter patches applied, and both research-archive checksums matching `SHA256SUMS`.
</Check>

```sh
node -e "const e=require('./package.json').engines.node; console.log(process.version, e)"
npm ci
(cd research-archives/original/0.18.0 && shasum -a 256 -c SHA256SUMS)
```

`npm run check` (`typecheck` + `source:typecheck` + `node --test tests/*.test.mjs`) can run after `npm ci` without packaging. The archives test still requires pulled LFS objects.

Contributor minimum after install (from `CONTRIBUTING.md`):

```sh
npm ci
npm run check
npm run frontend:build
```

On macOS, after bootstrap:

```sh
npm run package
npm run verify
```

## Install failures

| Symptom | Cause | Fix |
| --- | --- | --- |
| `engines` / unexpected Node | Interpreter outside `>=26.5.0 <27` | Install Node 26.5.x |
| DMG tens of kilobytes; test `requires git lfs pull` | LFS pointer, not the 155 793 020-byte object | `git lfs install && git lfs pull` |
| `Archived DMG checksum mismatch` | Corrupt or pointer archive | `git lfs pull`, then `shasum -c SHA256SUMS` |
| `Refusing to patch unexpected @connectrpc/connect input` | `node_modules` not lockfile-stock | Delete `node_modules` and re-run `npm ci` |
| `The reconstructed macOS application can only be packaged on macOS.` | `process.platform !== "darwin"` | Use Apple Silicon macOS for package/smoke |
| `Expected Grok Bot 0.18.0, got …` | `GROK_BOT_018_APP` is the wrong app version | Point at 0.18.0 or unset and use the LFS DMG |
| `hdiutil` / `codesign` exited non-zero | Missing CLT or Gatekeeper tool path | `xcode-select --install` |
| `Docker is not running.` | Optional daemon down | Ignore unless enabling local Docker VM |

<Warning>
Do not weaken checksum, bundle-id, or signing checks to get a green install. Those gates are required contributor policy.
</Warning>

## Next

<CardGroup>
<Card title="Quickstart" href="/quickstart">
Clone through `npm run package` and open `dist/Grok Bot 0.18 Reconstructed.app`.
</Card>
<Card title="Bootstrap the pinned runtime" href="/bootstrap-pinned-runtime">
`GROK_BOT_018_APP`, cached app, LFS DMG, then public URL; hydrate `src/app/dist`.
</Card>
<Card title="Preserve original installers" href="/preserve-original-installers">
LFS identities, `artifacts.json` schemaVersion 1, and `shasum -c SHA256SUMS`.
</Card>
<Card title="Enable the local Docker sandbox" href="/enable-local-docker">
Optional `grok-bot-local-vm` after Docker is installed and running.
</Card>
<Card title="npm scripts" href="/npm-scripts">
Exact `package.json` commands after `npm ci`.
</Card>
<Card title="Bootstrap failures" href="/bootstrap-failures">
Pointer-sized archives, checksum mismatch, and hydration errors.
</Card>
</CardGroup>
