# Bootstrap the pinned runtime

> npm run bootstrap order: GROK_BOT_018_APP, cached app, LFS DMG, then public URL; verify DMG and app.asar SHA-256; hydrate src/app/dist.

- 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

- `scripts/bootstrap-runtime.mjs`
- `scripts/lib/runtime.mjs`
- `scripts/lib/config.mjs`
- `tests/publication-bootstrap.test.mjs`
- `research-archives/original/0.18.0/artifacts.json`
- `research-archives/README.md`

---

---
title: "Bootstrap the pinned runtime"
description: "npm run bootstrap order: GROK_BOT_018_APP, cached app, LFS DMG, then public URL; verify DMG and app.asar SHA-256; hydrate src/app/dist."
---

`npm run bootstrap` runs `node scripts/bootstrap-runtime.mjs`. That script materializes a checksum-pinned Grok Bot **0.18.0** macOS arm64 Electron app into `.cache/runtime/Grok Bot.app`, then extracts `Contents/Resources/app.asar` into ignored `src/app/dist` after verifying the ASAR SHA-256. Later packaging (`npm run package`) copies that hydrated `src/app` tree and refuses to start without the cached 0.18.0 runtime.

<Note>
Bootstrap is a local, content-addressed input step. It does not choose an inference provider, start Docker, or write `dist/Grok Bot 0.18 Reconstructed.app`.
</Note>

## Prerequisites

| Requirement | Why bootstrap needs it |
| --- | --- |
| macOS Apple Silicon | The pinned installer is `darwin-arm64`. Extraction uses `/usr/bin/hdiutil`, `/usr/bin/ditto`, and `/usr/bin/plutil`. |
| Node `>=26.5.0 <27` | `package.json` `engines.node` |
| Git LFS | Preserved DMG at `research-archives/original/0.18.0/macos-arm64/Grok_Bot_0.18.0.dmg` |
| `npm ci` | `@electron/asar` is used to unpack `app.asar` |

```sh
git lfs install
git lfs pull
npm ci
npm run bootstrap
```

Optional: skip the DMG path by pointing `GROK_BOT_018_APP` at an already installed `Grok Bot.app` whose `CFBundleShortVersionString` is `0.18.0`.

## Resolution order

The script picks **one** runtime source, then always hydrates `src/app/dist` from that app's `app.asar`.

```mermaid
flowchart TD
  start([npm run bootstrap]) --> env{"GROK_BOT_018_APP set?"}
  env -->|yes| copyEnv["ditto into .cache/runtime/Grok Bot.app"]
  env -->|no| cachedApp{".cache/runtime/Grok Bot.app exists?"}
  cachedApp -->|yes| validateCached["validateRuntimeApp"]
  cachedApp -->|no| dmg["downloadDmg"]
  dmg --> cachedDmg{".cache/downloads/Grok_Bot_0.18.0.dmg matches pin?"}
  cachedDmg -->|yes| attach
  cachedDmg -->|no| lfs{"LFS archive exists?"}
  lfs -->|yes| verifyLfs["SHA-256 then copy to cache"]
  lfs -->|no| fetchUrl["GET dmgUrl → .partial → rename"]
  verifyLfs --> attach["hdiutil attach Grok Bot.app"]
  fetchUrl --> attach
  attach --> copyDmg["ditto into .cache/runtime/Grok Bot.app"]
  copyEnv --> hydrate
  validateCached --> hydrate
  copyDmg --> hydrate["hydrateSourcePayloadFromRuntime"]
  hydrate --> asarPin{"app.asar SHA-256 == upstreamAsarSha256?"}
  asarPin -->|yes| dest["replace src/app/dist"]
  asarPin -->|no| failAsar["throw checksum mismatch"]
```

### 1. `GROK_BOT_018_APP`

<ParamField body="GROK_BOT_018_APP" type="string">
Absolute or relative path to a `Grok Bot.app` bundle. The value is trimmed; empty/whitespace is ignored.
</ParamField>

When set, bootstrap never downloads a DMG. It validates the path, deletes any previous `.cache/runtime/Grok Bot.app`, and copies the bundle with `/usr/bin/ditto`.

### 2. Cached app

If the env var is unset and `.cache/runtime/Grok Bot.app` already exists, bootstrap only re-validates that copy.

### 3. Cached DMG, then LFS, then public URL

If no cached app exists, `downloadDmg()` fills `.cache/downloads/Grok_Bot_0.18.0.dmg`:

1. Reuse the cached DMG when its SHA-256 already matches the pin. A mismatched cache file is deleted.
2. If `research-archives/original/0.18.0/macos-arm64/Grok_Bot_0.18.0.dmg` exists, hash it. On match, copy it into the cache. On mismatch, throw and tell you to `git lfs pull`.
3. Otherwise `fetch()` the public URL with `redirect: "follow"`, write `.cache/downloads/Grok_Bot_0.18.0.dmg.partial` at mode `0o600`, verify SHA-256, then rename into the cache. A failed HTTP response or digest mismatch deletes the partial file.

The Windows `setup.exe` in the same archive is **not** a bootstrap input.

### 4. Extract `Grok Bot.app` from the DMG

`hdiutil attach -readonly -nobrowse -mountpoint` mounts the cached DMG under a temp directory named `grok-bot-018-mount-*`. Bootstrap copies `<mount>/Grok Bot.app` into the runtime cache, then detaches and removes the mountpoint.

## Pinned identities

Constants live in `scripts/lib/config.mjs` and must match `research-archives/original/0.18.0/artifacts.json` (`schemaVersion` `1`) for the macOS artifact.

| Pin | Value |
| --- | --- |
| `upstreamVersion` | `0.18.0` |
| `dmgUrl` | `https://downloads.cursor.com/grokbot/stable/darwin-arm64/0.18.0/Grok_Bot_0.18.0.dmg` |
| `dmgSha256` | `a253ccd8aab01e083f9812a0264354c5034d8ba7f0610bbb557e82ae77d203eb` |
| `upstreamAsarSha256` | `6665408168466f9cacc6087e917890c17f59d2e2e9c2404a5c4a59ad79c1de58` |
| macOS archive bytes | `155793020` |

Independent check of the LFS files (not performed by bootstrap itself):

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

`tests/research-archives.test.mjs` also requires each installer byte length to equal `artifacts.json` `bytes`. A Git LFS pointer file fails that size check.

## Runtime validation

`validateRuntimeApp()` runs on every accepted app (env copy, cache hit, or DMG extract):

| Check | Path / tool |
| --- | --- |
| Version | `plutil -extract CFBundleShortVersionString raw Contents/Info.plist` must equal `0.18.0` |
| Executable | `Contents/MacOS/Grok Bot` must be a file |
| Unpacked natives | `Contents/Resources/app.asar.unpacked` must be a directory |

Failure messages:

- `Expected Grok Bot 0.18.0, got <version> at <appPath>`
- `Incomplete Grok Bot runtime at <appPath>`

Packaging later calls `resolveRuntimeApp()`. If `GROK_BOT_018_APP` is unset and the cache is missing, it throws `Missing 0.18.0 runtime. Run \`npm run bootstrap\` first.`

## Hydrate `src/app/dist`

`hydrateSourcePayloadFromRuntime()` hashes `Contents/Resources/app.asar` as raw bytes. The digest must equal `upstreamAsarSha256`. It then:

1. Extracts the archive under `.cache/source-payloads/grok-bot-018-*`.
2. Requires these files to exist as regular files:
   - `dist/electron-main/main.cjs`
   - `dist/host/host-main.cjs`
   - `dist/renderer/index.html`
3. Deletes `src/app/dist` if present and copies only the archive's `dist/` tree there (`dereference: false`, timestamps preserved).
4. Deletes the temporary extract directory.

Checked-in `src/app/package.json` is not replaced. `/src/app/dist/` and `/.cache/` are gitignored; do not add the hydrated tree.

<Warning>
Hydration is the shipped renderer and compiled payload, not `frontend/`. Packaged UI stays this checksum-pinned `dist/renderer` unless a later packaging override is set.
</Warning>

`tests/publication-bootstrap.test.mjs` asserts a matching SHA-256 hydrates `dist/renderer/index.html` and that a wrong `expectedSha256` rejects with `/checksum mismatch/`.

## Paths and outputs

:::files
repo/
├── research-archives/original/0.18.0/
│   ├── artifacts.json
│   ├── SHA256SUMS
│   └── macos-arm64/Grok_Bot_0.18.0.dmg   # Git LFS
├── src/app/
│   ├── package.json                      # checked in
│   └── dist/                             # hydrated, gitignored
└── .cache/
    ├── downloads/Grok_Bot_0.18.0.dmg
    ├── runtime/Grok Bot.app
    └── source-payloads/grok-bot-018-*/
:::

<RequestExample>
```sh
npm run bootstrap
```
</RequestExample>

<ResponseExample>
```text
Using archived release .../research-archives/original/0.18.0/macos-arm64/Grok_Bot_0.18.0.dmg
Runtime ready: .../.cache/runtime/Grok Bot.app
Checksum-pinned source payload ready: .../src/app/dist (6665408168466f9cacc6087e917890c17f59d2e2e9c2404a5c4a59ad79c1de58)
The checksum-pinned app supplies only the Electron shell, ABI-matched native dependencies, and explicitly documented build fallbacks.
```
</ResponseExample>

When the LFS file is absent and the cache is empty, the first log line is `Downloading https://downloads.cursor.com/grokbot/stable/darwin-arm64/0.18.0/Grok_Bot_0.18.0.dmg` instead of `Using archived release`.

## What packaging consumes next

`scripts/lib/build-asar.mjs` copies the whole `src/app` directory (including hydrated `dist/`) into `.build/app`, then overlays ABI-matched `deps` and `native` trees from the cached app's `app.asar.unpacked`. The bootstrap console line is literal: the cached app is the Electron shell, native ABI, and documented fallbacks—not reconstructed TypeScript under `source/`.

## Failures bootstrap throws

| Symptom | Typical cause | What to do |
| --- | --- | --- |
| `Archived DMG checksum mismatch ... Run git lfs pull` | Pointer-sized or corrupt LFS object | `git lfs pull`, then `shasum -a 256 -c SHA256SUMS` |
| `DMG checksum mismatch` after download | Truncated or substituted URL payload | Delete `.cache/downloads/Grok_Bot_0.18.0.dmg*` and retry |
| `Download failed: HTTP <status>` | Public URL unavailable | Use LFS or `GROK_BOT_018_APP` |
| `Expected Grok Bot 0.18.0, got …` | Wrong app behind `GROK_BOT_018_APP` or stale cache | Point at 0.18.0 or remove `.cache/runtime` |
| `Incomplete Grok Bot runtime` | Missing `Contents/MacOS/Grok Bot` or `app.asar.unpacked` | Re-extract from the pinned DMG |
| `Upstream app.asar checksum mismatch` | ASAR is not the 0.18.0 pin | Do not bypass the hash; replace the runtime |
| `Upstream app.asar is missing dist/…` | Archive contents incomplete | Fail closed; do not hand-copy files into `src/app/dist` |

Full failure catalog: [Bootstrap failures](/bootstrap-failures).

## Next

<CardGroup>
  <Card title="Package the macOS app" href="/package-macos-app">
    Compile reconstructed runtimes, replace app.asar, ad-hoc sign, and verify.
  </Card>
  <Card title="Bootstrap failures" href="/bootstrap-failures">
    LFS pointers, checksum mismatches, version errors, and missing ASAR files.
  </Card>
  <Card title="Preserve original installers" href="/preserve-original-installers">
    artifacts.json schemaVersion 1, LFS DMG/EXE identities, SHA256SUMS.
  </Card>
  <Card title="Reconstruction boundary" href="/reconstruction-boundary">
    Ignored src/app/dist hydration versus compiled source/ runtimes.
  </Card>
</CardGroup>
