CLI
@preact-mvc/cli is the project toolkit — Angular CLI shaped: scaffold apps, generate views/controllers/services/ modules/islands, run the project's vite and vitest, add integrations, and bump framework deps.
Install
npm install -g @preact-mvc/cli
# or run without installing:
npx @preact-mvc/cli <command>The binary is pmvc (with PreactMVC as a longer alias). It is dependency-free Node — it must run before a project has node_modules at all.
New application
pmvc new my-app # core app: module + router + two views + a test
pmvc new my-app --islands # + worker-island demo (contract, worker, route)
pmvc new my-app --tailwind # + Tailwind v4 wired into vite and styles
pmvc new my-app --skip-install # write files onlyThe scaffold is the same shape this site documents: AppModule with RouterModule.forRoot, an AppShell view, a standalone HelloView, a stateful CounterView, jsdom test stubs, and the decorators-friendly tsconfig. Existing files are never overwritten unless --force; -d/--dry-run prints the plan without writing.
Generators
pmvc g view user-card # src/app/user-card/user-card.view.tsx (+ .test.tsx)
pmvc g controller checkout # checkout.controller.ts — @Controller view logic
pmvc g service session # session.service.ts — @Injectable model
pmvc g module admin # admin.module.ts — feature module
pmvc g island ticker # islands/ticker.contract.ts + workers/ticker.worker.tsx
pmvc g view report --path src/app/admin # override the target directory
pmvc g view report --skip-tests # no spec fileGenerators print the next step — the route entry or declaration to add — rather than editing files in place. The island generator emits the contract-first shape (worker factory inside the contract, islandComponent on the shell); run pmvc add islands first if the atoll packages are not installed.
Serve, build, test
Thin pass-throughs to the project's own toolchain — every flag after the command goes to vite/vitest:
pmvc serve --port 3000 # vite dev server
pmvc build # tsc --noEmit && vite build (--no-typecheck to skip)
pmvc test # vitest run
pmvc test --watch # vitest watch modeIntegrations
pmvc add tailwind # deps + vite plugin + styles.css
pmvc add islands # @preact-mvc/atoll + atoll-island + @atolljs/coreUpdates
pmvc update # bump every @preact-mvc/* dep to latest, npm install
pmvc update --to 0.2.0 # pin to a specific release
pmvc update -d # show the planned changes only
pmvc update --include-atoll # also bump @atolljs/* depspmvc version prints the CLI version plus the detected framework dep ranges of the project you're inside.
Generated tests mount views through
InjectorContext.Provider— a barerender()has no injector context, soinject()throws by design. The generated vite config keeps the whole preact graph in one vitest realm for the same reason.