Fixes the v0.3.4 fresh-box failures: silent CLI under bare-word PATH invocation (SEA argv detection), bootstrap dying on venv creation without an actionable hint (poisoned-partial-venv recovery + apt hint + doctor venv-capability probe + preflight), installer falsely 'verifying' a silent binary, and localhost-only server binding (network mode: 0.0.0.0 + wildcard CORS + hostname-derived API URL — remote browsing zero-config). 38 CLI tests, 3 web tests, 409 ai-service tests green; build/typecheck/lint clean. ---ci--- phase: hotfix milestone: v0.4 status: complete type: hotfix requirements: covered: [REQ-4-001, REQ-4-002, REQ-4-003, REQ-4-004, REQ-4-005] partial: [] ---/ci---
@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 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 toapps/ai-service/scripts/*.shviasrc/lib/spawn.ts(array-args only, SIGTERM→SIGKILL timeout ladder)src/checks/— pure logic: version compare,.envtemplate difftests/— 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
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 <tag> # SEA binary + sha256 sidecar
build:binary <tag>: 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 <tag> after tag+merge:
- Builds the binary stamped with the tag
- Resolves
GITEA_TOKENfrom.env*files ONLY (.ciagent/.env.secretsfirst) — never from shell env - Attaches
nextcraft-linux-x64+nextcraft-linux-x64.sha256to 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 |