Scaffolding CLI
@wise-wig/cli turns the framework contracts that are concrete in alpha into guarded, repeatable starting points. It is currently a repository-local developer tool; the site template uses workspace:* packages and is not yet a standalone published create-wise-wig package.
Run commands from the repository root:
pnpm wise-wig help
pnpm wise-wig create site examples/acme-coffee --title "Acme Coffee"
pnpm wise-wig generate component testimonial-grid --cwd examples/acme-coffee --max-instances 3
pnpm wise-wig generate theme summer --cwd examples/acme-coffee
pnpm wise-wig generate plugin sermons --kind native --scope @agency --cwd packages/sermons
pnpm wise-wig generate plugin surveys --kind sandboxed --scope @agency --publisher did:plc:example --cwd packages/surveys
pnpm wise-wig plugin validate packages/surveys/src/plugins/surveys --json
pnpm wise-wig plugin verify-release --publisher did:plc:abcdefghijklmnopqrstuvwx --package sermons --version 1.0.0 --json
pnpm wise-wig generate hosting-provider fly-io --cwd packages/hosting-fly
pnpm wise-wig cloudflare plan --profile core --cwd examples/acme-coffee
pnpm wise-wig doctor --profile core --cwd examples/acme-coffee
All artifact generators refuse to replace an existing file unless --force is explicit. --dry-run reports planned paths without writing, and --json produces machine-readable output suitable for agents and scripts. Names are restricted to portable lowercase slugs so they cannot escape their generated directory.
Site scaffold
create site copies the tested Morning Bell Astro vertical slice rather than maintaining a second, less-tested template. It excludes dependencies, build products, Wrangler state, local secrets, and Git metadata. The generated site receives its own package identity, Worker name, local typed content seed, and startup notes.
What works immediately inside this monorepo:
- five addressable pages (Home, About, Services, Gallery, and Contact) with navigation, SEO descriptions, contact details, and a validated contact form
- Astro SSR public, preview, and edit modes using the same built-in component renderers
- React editor overlay and local browser-extension handoff
- guarded draft edits, structural mutations, publishing, management UI, and Cloudflare adapter boundaries inherited from the example
- guided page creation from four approved layouts, duplication, SEO/route edits, ordering, deletion redirects, and atomic page/navigation/redirect publication
- a page-aware in-memory local content seed branded with the requested site title
The local repository resets on server restart. Production still requires real identity configuration and the Cloudflare resources in Cloudflare deployment. The generator intentionally leaves replace-me binding values visible; doctor warns until they are configured.
Artifact generators
Component
Generates a Zod component definition, an Astro renderer with conditional edit metadata, and an adjacent integration checklist. The default fields are a bounded plain-text heading and portable richTextSchema body; the renderer uses the shared escaped rich-text renderer. Developers should change this schema before registration.
The alpha document schema and editor controls are still closed unions. A generated component is therefore not accepted automatically. Its checklist calls out the component registry, document discriminated union, Astro render dispatch, mutation allowlist, and editor control registry that must agree. Automatic component discovery belongs after those boundaries can remain type-safe.
Theme
Generates a host-neutral ThemeDefinition with separate appearance tokens, stable layout slot IDs for the complete built-in marketing catalog, optional Tailwind build hints, and a plain-CSS custom-property foundation. Register the result in a host ThemeRegistry, attach its data-wise-wig-theme attribute to the document shell, and ship its Astro layout implementation with the site. Tailwind can consume the generated variables without becoming a framework requirement. The scaffold does not claim automatic theme discovery or a signed catalog.
Plugin
--kind native creates a definePlugin module for trusted, developer-deployed code. It runs at the site’s trust level and must receive the same review as theme code.
--kind sandboxed creates an EmDash-compatible package: emdash-plugin.jsonc is the canonical identity and trust contract, src/plugin.ts uses EmDash’s type-only plugin contract, and optional wisewig-plugin.jsonc holds AI/MCP declarations. Set the real EmDash publisher DID with --publisher. plugin validate runs the pinned upstream build and validate-only bundle pipeline, then compiles the sidecar and prints the internal fail-closed contract. It is only for developer-controlled source: the EmDash probe may execute that source with the CLI process’s authority. Never use it to inspect an untrusted registry artifact or run it with platform credentials. The WiseWig sidecar cannot add content, media, network, or storage authority beyond the EmDash manifest.
plugin verify-release is the untrusted-registry verification path and requires Node 22 or newer. It does not trust an aggregator payload: it verifies the exact release record’s compact CAR proof against the publisher’s current DID signing key and repository MST, validates the EmDash lexicon and requested identity, then downloads and checksum-verifies the bounded artifact. It currently verifies only direct, public artifacts; authenticated and redirect-oriented release assets fail closed. The command verifies but does not install or execute the bundle. Executing a verified registry bundle still requires the sandbox adapter described in EmDash plugin compatibility and WiseWig AI.
Hosting provider
Generates an implementation stub for the host-neutral HostedProvider boundary: domain verification, deployment, and hostname activation. Provider code receives identifiers and secret references, never CMS credential values. The scaffold deliberately throws until each provider-specific operation is implemented.
Not scaffolded yet
The CLI does not generate arbitrary collections, new media kinds beyond the built-in image/video/download contracts, MCP deployments, migrations that mutate the central document union, credentials, or production identity configuration. Those contracts are either intentionally centralized for safety or not concrete enough in alpha. Add generators only after the corresponding runtime, validation, security, and upgrade contracts exist.
Cloudflare deployment assistance
Cloudflare installations use two required Workers and three optional Workers, exposed through four convenient profiles. The ai profile keeps the public/private MCP security pair together:
| Profile | Workers |
|---|---|
core | Astro site and tenant workspace |
plugins | Core plus the isolated plugin sandbox |
ai | Core plus physically separate public and private MCP gateways |
full | Core plus all three optional Workers |
cloudflare plan prints the selected Workers, shared resources, secret names, and safe deployment order. Its --json form is intended for CI and AI agents. It never reads or prints secret values.
After building the Astro site, cloudflare prepare creates profile-specific Wrangler files. The core and AI profiles remove PLUGIN_SANDBOX; every self-hosted profile removes the managed-only HOSTING_DEPLOYER. This makes the two-Worker core honest while retaining physical isolation when plugins are selected:
pnpm --filter @wise-wig/acme-coffee build
pnpm wise-wig cloudflare prepare --profile core --cwd examples/acme-coffee --deployment-config .wise-wig/cloudflare.local.json
pnpm wise-wig doctor --profile core --cwd examples/acme-coffee
pnpm --filter @wise-wig/tenant-workspace-worker exec wrangler deploy --dry-run --config wrangler.wise-wig-core.jsonc
pnpm --dir examples/acme-coffee exec wrangler deploy --dry-run --config dist/server/wrangler.wise-wig-core.json
The v2 managed-isolated topology uses a separate, fail-closed preparation mode. It retains the exact TENANT_DISPATCH service binding, removes direct TENANT_WORKSPACE and PLUGIN_SANDBOX capabilities, and produces a dedicated configuration:
pnpm --filter @wise-wig/acme-coffee build
pnpm wise-wig cloudflare prepare --managed-isolated --cwd examples/acme-coffee
pnpm wise-wig doctor --managed-isolated --cwd examples/acme-coffee
pnpm --dir examples/acme-coffee exec wrangler deploy --dry-run --config dist/server/wrangler.wise-wig-managed-isolated.json
--managed-isolated and --profile are mutually exclusive. The removed --managed name is rejected because it could imply a weaker shared topology. Preparation refuses a built Astro configuration unless it contains exactly one TENANT_DISPATCH binding pinned to wisewig-tenant-dispatch; it then removes shared D1, R2, public KV, tenant Durable Object, plugin sandbox, operator deployer, and platform-secret capabilities. The managed-isolated doctor verifies both the dispatcher pin and that complete denylist. This is a v2 deployment security gate, not part of the self-hosted beta path.
Generated deployment configurations live beside their source or built Wrangler configuration and are excluded from version control. Refresh them explicitly with --force after a build or profile change. Do not edit them; fix the source configuration or the validated, non-secret deployment descriptor and regenerate. The descriptor hydrates D1, KV, R2, Queue, OAuth endpoints and distinct site/private-MCP client IDs, public-origin, trust-key, and optional Analytics Engine values across every selected Worker. Secrets remain separate wrangler secret put inputs.
After all five full-profile Workers are deployed, run cloudflare self-hosted preflight --operator <name> --public-mcp-url https://…/mcp. It is read-only, verifies the exact deployed capability names and live public MCP identity, and writes a private redacted receipt under .wise-wig/evidence. It returns nonzero for an unclean commit, unresolved prepared config, missing Worker, unavailable MCP, or any required/forbidden binding mismatch.
For self-hosted profiles, doctor validates every selected Worker configuration, required bindings, unresolved IDs and example URLs, prepared replace-*/pending-* values, the D1 migration directory, and a workspace-local Wrangler v4 declaration. Self-hosted private MCP binds directly to the tenant workspace Durable Object namespace and does not require a Workers for Platforms entitlement or tenant_workers row. In managed-isolated mode the doctor validates the generated Astro capability boundary. Source-template warnings identify values that the deployment descriptor replaces; unresolved values in a prepared config are errors and mean the selected topology cannot be deployed safely.
Wrangler is intentionally invoked from the relevant workspace rather than assumed to be global. Resource creation and wrangler secret put remain interactive operations so credentials never appear in generated plans, command arguments, logs, or committed files.
V2 managed-isolated preflight
Before a future v2 managed-isolated drill, run the read-only preflight from a clean release commit:
pnpm wise-wig cloudflare managed-isolated preflight \
--cwd examples/morning-bell-coffee \
--operator "release-operator" \
--namespace wisewig-staging
The defaults wisewig-drill-a and wisewig-drill-b are intentionally restrictive. Custom --tenant-a and --tenant-b values must be distinct and retain the wisewig-drill- prefix; the CLI refuses customer-like identifiers. It checks the generated managed Astro boundary, clean Git state and release digest, workspace-scoped Wrangler authentication, and dispatch-namespace entitlement. Every Cloudflare call is read-only.
The command writes a mode-0600, schema-versioned JSON receipt beneath the selected site’s .wise-wig/evidence/ directory. That directory is ignored by Git. Receipts contain stable check codes and the release digest, but never raw Wrangler output, account details, secret values, or credential inventory. Use --dry-run to print the same result without writing a receipt and --json for agent/CI consumption.
Exit zero means the account is ready for the separately documented v2 provisioning drill. A nonzero WORKERS_FOR_PLATFORMS_NOT_ENABLED result means the account needs dispatch-namespace entitlement; it does not block the self-hosted beta and does not authorize substituting a shared Worker or weakening the future hosted boundary. The preflight itself never creates, deploys, modifies, or deletes Cloudflare resources.
Validation
CLI tests create temporary projects, assert sensitive/build files are excluded, validate naming and overwrite controls, inspect each generated contract, exercise doctor, and prove beta-preflight containment, fail-closed binding checks, entitlement classification, receipt permissions, and output redaction. Normal repository gates remain:
The end-to-end product gate is documented in Agency five-page workflow.
pnpm test
pnpm check
pnpm build