# AGENTS.md for @webjsdev/cli

The webjs **command-line interface** (`webjs dev` / `start` / `test`
/ `check` / `create` / `db`) plus the scaffold templates shipped
into every new app.

Framework-wide rules (workflow, JSDoc-in-`packages/`, no-build,
commit conventions, autonomous-mode behaviour, scaffold rules) live
in the **framework root [`../../AGENTS.md`](../../AGENTS.md)** and
apply here. Read that first.

This file only covers what's specific to `@webjsdev/cli`.

## Module map

```
bin/
  webjs.js               CLI entry: argv dispatch for every command.
                         The exact-three template list (full-stack/api/saas)
                         is enforced here; --template validation rejects
                         anything else with a guidance message.
lib/
  node-preflight.js      Inline, DEPENDENCY-FREE Node-version guard (#238).
                         `checkNodeInline(current, engines)` + `nodeInlineMessage`.
                         The bin runs it BEFORE any `import @webjsdev/server`,
                         because importing the server links dev.js (Node 24+
                         builtins) and would itself link-fail on old Node. So the
                         primary guard depends only on `process.versions.node`.
                         Tests: `test/node-preflight/`.
  (MCP moved out)        The MCP server (`webjs mcp` + the `check --json` JSON
                         projector) was EXTRACTED into the standalone
                         `@webjsdev/mcp` package (#415). `webjs mcp` now
                         delegates to its `runMcpServer`, and `check --json`
                         imports `projectCheck` from `@webjsdev/mcp/check-report`
                         (so the CLI flag and the MCP `check` tool stay
                         byte-identical). `@webjsdev/mcp` is a `dependencies`
                         entry. See `packages/mcp/AGENTS.md` for the full surface
                         (tools, resources, prompts, the source tool, the docs
                         bundling). Agents register the server via
                         `npx @webjsdev/mcp`.
  doctor.js              `webjs doctor` project-health checks (#266).
                         `runDoctorChecks(appDir, opts?)` is PURE (reads files +
                         optionally the network, never exits / prints) so each
                         check is unit-testable. `opts.nodeVersion` overrides the
                         running Node, `opts.vendor` injects the pin-freshness
                         `{ hasVendorPin, findOutdated }` pair (offline tests).
                         The bin renders + owns the non-zero exit on a hard fail.
                         Tests: `test/cli/doctor.test.mjs`.
  port.js                Port resolution for `webjs dev` / `start` (#447).
                         `loadAppEnv(appDir)` loads `<appDir>/.env` into
                         `process.env` (same guard + shell-wins semantics as the
                         server's own load); `resolvePort(portFlag, env?)` is the
                         PURE resolver with precedence `--port` > `PORT` (real env
                         or `.env`) > 8080. The bin calls `loadAppEnv` BEFORE
                         `resolvePort` so a `.env` PORT is in `process.env` at
                         resolution time; the server loads `.env` too but too late
                         to affect the port the CLI computes. Tests: `test/port/`.
  create.js              `webjs create <name>` scaffold logic. Copies
                         `templates/` into the new app, writes
                         package.json + tsconfig + Prisma schema,
                         template-specific app/ files, prints the
                         post-scaffold guidance for AI agents.
  saas-template.js       Extra files written when --template saas:
                         auth + login/signup + protected dashboard
                         + Prisma User model.
templates/               Verbatim files copied into every new app.
                         {{APP_NAME}} placeholder is substituted at
                         copy time. The AGENTS.md / CLAUDE.md /
                         CONVENTIONS.md / .cursorrules / .agents/rules/workflow.md
                         / .github/copilot-instructions.md / .editorconfig
                         / .env.example / .claude.json / .claude/hooks/
                         all live here.
README.md                npm-facing package readme.
```

## Public commands (see USAGE in `bin/webjs.js`)

| Command | Implementation |
|---|---|
| `webjs dev` | Spawns `node --watch` re-entry, then `startServer({ dev: true })`. In the parent (pre-spawn) it runs the Prisma-client preflight (`lib/prisma-preflight.js`, #452): for a Prisma app (a `prisma/schema.prisma` or an `@prisma/client` dep) whose generated client is missing/stale, it prints a hint pointing at `npm run dev` (the canonical command, which runs the `predev` `prisma generate` hook) or `webjs db generate`. A bare `webjs dev` skips `predev`; the hint replaces the raw crash. Non-Prisma apps get nothing. A hint only, never an auto-run. |
| `webjs start` | `startServer({ dev: false })`, plain HTTP/1.1 (front a reverse proxy for TLS + HTTP/2) |
| `webjs test [--server\|--browser]` | `node --test` for server tests, `wtr` for browser tests |
| `webjs check [--rules] [--json]` | `checkConventions()` from `@webjsdev/server/check`. `--rules` lists the checks. `--json` emits the structured violations + a summary count as JSON (via `projectCheck` from `@webjsdev/mcp/check-report`, the same projector the MCP `check` tool uses, #415), so an agent in a loop consumes structured data instead of regex-scraping stdout; the non-zero exit on violations is preserved. Report-only: each violation carries a prose `fix` hint, but there is no `--fix` autofix flag (the rules either rewrite code or rename files, so an automatic codemod is not safe) |
| `webjs mcp` | Delegates to `runMcpServer()` from the standalone `@webjsdev/mcp` package (#415; full surface in `packages/mcp/AGENTS.md`). A read-only MCP stdio server: INTROSPECTION (`list_routes` / `list_actions` / `list_components` / `check`), KNOWLEDGE (`init` primer, `docs`, `resources`, `prompts`), and a `source` tool. The scaffold's `.claude.json` registers the server directly as `{ "command": "npx", "args": ["@webjsdev/mcp"] }` (mountable in any MCP host, e.g. Cursor `.cursor/mcp.json`); `webjs mcp` stays as a back-compat alias. STDOUT is the JSON-RPC channel (diagnostics go to stderr) |
| `webjs doctor` | `runDoctorChecks()` from `lib/doctor.js`. A project-health checklist over existing signals (Node major, tsconfig `erasableSyntaxOnly`, `.env` drift vs `.env.example`, vendor-pin freshness, the `.gitignore` keeping `.webjs/vendor/` committable (`vendor-gitignore`, moved here from `webjs check` in #461 as a warn since it is a project-config concern, not source correctness), `@webjsdev/*` version coherence, importmap coherence, git pre-commit hook). PURE checks render with a `[pass]` / `[warn]` / `[fail]` marker; non-zero exit iff a HARD check fails (Node below the floor, or `erasableSyntaxOnly` missing in an existing tsconfig), so CI can gate. Warns (drift / staleness) never fail the exit. The only network touch (pin freshness, plus the importmap-coherence live resolve) is best-effort: a fetch failure is a warn, never a hard fail. The importmap-coherence check (#450) runs `@webjsdev/server`'s `checkImportmapCoherence` IDENTICALLY over the live importmap AND the vendored `.webjs/vendor/importmap.json`, warning when a pinned package needs a newer version of another pinned package than is pinned (the #446 skew class); it reads dependency metadata from the already-installed node_modules manifests (no network of its own) and degrades to "could not verify" when a manifest is unavailable. An onboarding/setup-verify tool, NOT a scaffold-CI hard gate. Tests: `test/cli/doctor.test.mjs` |
| `webjs types` | `generateRouteTypes()` from `@webjsdev/server`, writes `.webjs/routes.d.ts` (typed `Route` union + per-route params, #258). Also auto-emitted at `webjs dev` startup |
| `webjs typecheck [tsc args]` | Resolves the project's own `typescript/bin/tsc` (via `createRequire` from the app cwd) and spawns it with `--noEmit`, passing extra args through. Exits non-zero on a type error (a CI gate). A clear message + non-zero exit when typescript is not installed (#265). The framework runs the standard compiler, it does not embed one |
| `webjs create <name> [--template …]` | `scaffoldApp()` from `lib/create.js` |
| `webjs db <generate\|migrate\|studio>` | Passthrough to `prisma` |
| `webjs ui <init\|add\|list\|view\|diff\|info>` | Proxies to `@webjsdev/ui` (see "UI subcommand" below) |

## UI subcommand: proxies to `@webjsdev/ui`

`@webjsdev/ui` is a **hard dependency** of `@webjsdev/cli` (listed in
`package.json` `dependencies`), so a global `webjs` install always ships
with the AI-first component CLI out of the box, no separate install.

`webjs ui <subcmd> [args...]` is a thin dispatch into `@webjsdev/ui`'s
`run({ argv })` entry. The implementation lives in
[`bin/webjs.js`](./bin/webjs.js) under `case 'ui':`. It resolves
`@webjsdev/ui` via `createRequire` rooted at the CLI's own location first
(the hard-dep path), with a fallback to the user's `cwd` for the rare case
where the user installed `@webjsdev/ui` directly without going through
`@webjsdev/cli`.

The subcommands (`init`, `add`, `list`, `view`, `diff`, `info`) are owned
and documented by `@webjsdev/ui`. See
[`../ui/AGENTS.md`](../ui/AGENTS.md) for the surface. The CLI does not
wrap or transform args; everything after `webjs ui` is forwarded
verbatim.

## Package-specific invariants

1. **Exactly three templates.** `full-stack` (default), `api`, `saas`.
   The `TEMPLATES` array in `bin/webjs.js` is the single source of
   truth, and `scaffoldApp()` re-validates programmatically. Hallucinated
   templates (`blog`, `todo`, `ecommerce`, …) are rejected at the CLI
   with a guidance message.
2. **Scaffold is reference, not the final product.** The scaffold
   output ships an example `app/page.ts` ("Hello from …"), an example
   `User` Prisma model, an example `theme-toggle` component. AI agents
   asked to build a real app MUST replace those with the actual app.
   The post-scaffold success message in `lib/create.js` prints this
   rule verbatim.
3. **Prisma + SQLite is wired up for ALL templates.** `prisma/schema.prisma`,
   `lib/prisma.ts`, `npm run db:migrate`, `predev` / `prestart` hooks.
   Apps must NEVER use JSON files for persistence. This is a project
   convention (documented in the scaffold's CONVENTIONS.md).
4. **Template files are verbatim copies** with `{{APP_NAME}}` substitution.
   When editing `templates/AGENTS.md`, `templates/CLAUDE.md`,
   `templates/CONVENTIONS.md`, `.cursorrules`, etc., remember they ship
   into every scaffolded app. Write for the audience of an AI agent
   working inside a freshly-scaffolded webjs project.
5. **`templates/CLAUDE.md` uses Claude Code's `@import` syntax**
   (`@AGENTS.md`, `@CONVENTIONS.md`). See https://code.claude.com/docs/en/claude-md.md#import-additional-files

## Tests

Scaffold-template tests for this package live in cross-package
folders under the repo root (they need to boot scaffolded apps):
`test/scaffolds/scaffold-template-validation.test.js`,
`test/scaffolds/scaffold-integration.test.js`,
`test/scaffolds/scaffold-ui-integration.test.js`.

Convention-rule tests live in
`packages/server/test/check/check.test.js` (the rules themselves
ship from `@webjsdev/server`).

End-to-end testing of the actual scaffold output is currently
manual (`webjs create demo && cd demo && webjs dev`, since `webjs create` auto-installs).
See [`../../agent-docs/testing.md`](../../agent-docs/testing.md)
for the overall layout.

Run `npm test` from the repo root.

---

Framework-wide rules and full API reference:

@../../AGENTS.md
