Files
nextcraft/apps/cli/README.md
T
CIAgent 2c68b44c1a merge: milestone/v0.4-distribution → main (v0.4 Distribution & Bootstrap CLI complete)
The nextcraft bootstrap CLI ships: doctor/bootstrap/verify/dev commands, a
one-liner install script with checksum + version integrity gates, and linux
x64 SEA binaries published on every release going forward (v0.3.2 onward).
Fresh-clone E2E proven; 34 CLI tests + full monorepo gates green.

Escalation note: merge_to_main hook — proceeding per full autonomy + founder
directive D-016 (streamlined install + bootstrap CLI + ongoing binaries,
recorded at P0 SPECIFY).

---ci---
phase: 4
milestone: v0.4
status: complete
requirements:
  covered: [REQ-4-001, REQ-4-002, REQ-4-003, REQ-4-004, REQ-4-005]
  partial: []
---/ci---
2026-09-12 23:17:43 +00:00

3.3 KiB

@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 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

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:

  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