# @nextcraft/cli — nextcraft The bootstrap CLI for the Nextcraft monorepo, shipped as a self-contained linux x64 binary (Node SEA) on every release. ## Commands See the [root README quickstart](../../README.md) for the user-facing flow. Internals: - `src/index.ts` — argv dispatch, exit-code contract (0 ok / 1 failure / 2 usage), direct-run guard (`argv[0] === argv[1]` detects SEA context — the installer renames the binary, so filename matching is unreliable) - `src/commands/` — doctor / bootstrap / verify / dev; all orchestration delegates to `apps/ai-service/scripts/*.sh` via `src/lib/spawn.ts` (array-args only, SIGTERM→SIGKILL timeout ladder) - `src/checks/` — pure logic: version compare, `.env` template diff - `tests/` — node:test suites: dispatch, checks, spawn, command stubs, real-box doctor integration, install.sh fixture-server E2E (tamper rejection, degradation), release-assets token isolation, fresh-clone E2E ## Build ```sh pnpm cli:typecheck # tsc --noEmit pnpm cli:test # node:test suites pnpm cli:build # tsc -p tsconfig.build.json -> dist/ pnpm --filter @nextcraft/cli build:binary # SEA binary + sha256 sidecar ``` `build:binary `: esbuild bundle (CJS, node18 target, version stamped via `NEXTCRAFT_VERSION_STAMP` define — `--version` reports the tag it was built as) → `node --experimental-sea-config` → postject injection into a copy of the system node binary → `dist/nextcraft-linux-x64` + `dist/nextcraft-linux-x64.sha256`. The binary runs without node on PATH (runtime embedded, ~117 MB). ## Release pipeline Every ship from v0.3.2 onward runs `scripts/release-assets.sh ` after tag+merge: 1. Builds the binary stamped with the tag 2. Resolves `GITEA_TOKEN` from `.env*` files ONLY (`.ciagent/.env.secrets` first) — never from shell env 3. Attaches `nextcraft-linux-x64` + `nextcraft-linux-x64.sha256` to the Gitea release (bounded retry, best-effort — never blocks the ship) `scripts/install.sh` (POSIX sh, dash-safe): platform gate → Gitea latest-release API resolve → exact-name asset match → sha256 verify BEFORE install (mismatch = hard stop) → `~/.local/bin` install → PATH hint. Any failure degrades to printed source-bootstrap instructions. ## Secrets policy The CLI never generates, writes, or echoes secrets. `bootstrap` copies `.env.example` → `.env` only when absent and warns on missing optional keys (mock providers keep the stack runnable keyless). Real keys live only in gitignored `.ciagent/.env.secrets`, exported by `apps/ai-service/scripts/dev.sh`. ## Troubleshooting | Symptom | Cause / fix | |---------|-------------| | `pnpm not found` in doctor | `corepack enable pnpm` (installs to ~/.local/bin — ensure PATH includes it) | | doctor passes but verify fails on venv | re-run `nextcraft bootstrap` (venv/pip resolution is idempotent) | | `port 8420 busy` in verify | stop the process on :8420 (`kill $(lsof -t -i:8420)`) or set `AI_PORT` | | install.sh says "no binary assets yet" | release predates the binary pipeline (pre-v0.3.2); use source bootstrap | | Binary silent after rename | fixed since v0.3.2 (SEA argv detection); re-download the latest release | | Checksum mismatch on install | do NOT run the download; delete it and retry — report if it persists |