# `ninja` — BlockNinja developer CLI The `ninja` command: build/verify/publish CMS plugins & themes, drive the plugin registry, and capture theme preview screenshots. Its own repo since WO-WZ-023 (remote `git.dev.alexdunmow.com/block/cli`); formerly lived inside `cms`. Go module `git.dev.alexdunmow.com/block/cli` (Go 1.26). Cobra CLI. Talks to the orchestrator over Connect-RPC; builds `.bnp` artifacts with `block/core` + wazero; screenshots with chromedp. ## Build / install / test ```bash make build # → ./bin/ninja make install # go install ./cmd/ninja → $GOBIN (yields `ninja` on PATH) make test # go test ./... (compiles guest wasm fixtures: needs GOOS=wasip1 + core proxy) make proto # regenerate the vendored orchestrator client (see below) make safety-check # cd ../check-safety && go run . ../cli ``` > **`make install` matters.** `ninja plugin publish` / `ninja plugin build` use > the binary on your PATH, not the repo. After changing build/pack behaviour you > MUST `make install` before any publish or the old binary ships. The classic > failure: an installed binary that predates `.bnp` preview-packing silently > republishes a theme **without** its `preview.png`, wiping the live preview. > Verify with `ninja theme screenshot --help | grep screenshots-dir` and by > extracting a fresh `.bnp` (`ninja plugin verify ` → `preview=true`). ## Command surface - `ninja plugin build | verify | publish | init | status | bump [major|minor|patch]` - `ninja plugin list | delete | delete-version | pull | version | abi` - `ninja plugin tags add|rm|set|clear` - `ninja scope create|default|set|list` - `ninja account list|set|show` · `ninja login | whoami | logout` - `ninja theme screenshot` (preview + `--pages`/`--screenshots-dir` multi-page capture) ## `.bnp` artifacts A `.bnp` is a **zstd-compressed tar** (NOT gzip — `tar tzf` won't read it; use `tar tf` or `ninja plugin verify`). `internal/bnp` owns build+verify; wasm plugins and codeless plugins/themes both pack into one. Optionally packs a root `preview.png` and a `screenshots/` dir (validated: png/jpg/jpeg/webp, ≤8MB/file, ≤12 files, no subdirs). `internal/shot` renders pages via chromedp for `ninja theme screenshot`. **Publish builds the artifact itself.** `ninja plugin publish` builds the `.bnp` and ships it — the artifact is the ONLY publish form (the legacy source-archive path is deleted). `--bnp ` ships a prebuilt one. Instances download the artifact and never compile. ## Orchestrator target (dev vs prod) Global `--host` flag: orchestrator base URL. **Default is `https://my.blockninjacms.com` — PRODUCTION.** For local dev always pass `--host https://my.blockninja.dev` (or set it as the active host via `ninja login`). Never publish dev/test plugins to the prod registry by omitting `--host`. Auth is **device flow** (`ninja login` → `AuthService.StartDevice`/`PollDevice`). Credentials (per-host token + active account) persist to `/ninja/credentials.json` (Linux: `~/.config/ninja/…`). `internal/creds` reads/writes it; `internal/orchclient` builds the Connect client. ## Vendored orchestrator proto (NOT a submodule) `proto/orchestrator/v1/plugin_registry.proto` is a **hand-vendored COPY** of the orchestrator's proto, not a git submodule. `make proto` regenerates `internal/api/orchestrator/v1/` from it. `buf.gen.yaml` runs in **managed mode** and overrides `go_package_prefix` → `git.dev.alexdunmow.com/block/cli/internal/api` so the generated Go lands in this module regardless of the proto's declared `go_package`. Needs `buf` + `protoc-gen-go` + `protoc-gen-connect-go` on PATH. **To pick up new orchestrator RPCs** (e.g. registry gallery/review methods): copy the updated `plugin_registry.proto` (and any new proto) from the orchestrator's proto into `proto/`, run `make proto`, then add client methods in `internal/orchclient`. There is no automatic sync — the copy is deliberate so the CLI pins a known server surface. ## Workspace couplings - `make safety-check` shells into the sibling `../check-safety` tool — the CLI is scanned like the other repos. Run it before publishing CLI changes. - Depends on `git.dev.alexdunmow.com/block/core` (the plugin SDK) via the Gitea module proxy. **Never** use `replace` directives — tag/push `core`, then bump. - The `.bnp` format + pack/validation rules are shared truth with the CMS host loader and the orchestrator registry ingestion; changing them is a cross-repo contract change. ## Working in here - Standalone repo: commit/push only within `cli/`. Work on `main`. - Ask before publishing anything to a registry — publish is outward-facing and hits a real orchestrator (prod by default).