docs: add CLAUDE.md (build/install, .bnp packing, vendored proto, dev vs prod host)

The make install landmine (stale binary republishes themes without preview.png
and wipes the live preview), the zstd-tar .bnp format, publish-builds-the-artifact,
the vendored-not-submodule orchestrator proto workflow, and the prod-by-default
--host all live in one place for the next agent working in here.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alex Dunmow 2026-07-05 09:20:17 +08:00
parent e8aba45f21
commit 64d81bd93f

94
CLAUDE.md Normal file
View File

@ -0,0 +1,94 @@
# `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 <file.bnp>``preview=true`).
## Command surface
- `ninja plugin build | verify <f.bnp> | 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 <file>` 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.localdev.blockninjacms.com` (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
`<os.UserConfigDir>/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).