CLI reference
The jorvel CLI ships every workflow you need — scaffold, dev, build, federation, SSR, quality gates, deploy. Run jorvel --help or jorvel <cmd> --help for the live command list.
Where commands run
Most commands work from anywhere in the workspace. Per-app commands (e.g.
jorvel routes) infer the target from your current directory. Use --app <name> to override.Project commands
| Command | Purpose |
|---|---|
npm create jorvel@latest <name> | Shorthand for jorvel init via the create-jorvel package (works with pnpm/yarn/bun create too) |
jorvel init <name> | Scaffolds a runnable app — workspace + starter host + remote, auto-wired. cd, install, jorvel dev and it runs (create-next-app style) |
jorvel init <name> --no-app | Bare workspace only — skip the starter host + remote |
jorvel init <name> --template <t> | Starter template: host-remote (default) · saas · blank |
jorvel init <name> --pm <m> | Package manager: pnpm (default) · npm · yarn · bun |
jorvel init <name> --tailwind | Wire Tailwind v3 + PostCSS in the scaffolded apps |
jorvel generate host <name> | Add a host app (React). Interactive: prompts to add Tailwind |
jorvel generate remote <name> | Add a remote — auto-wired into the host (federation + host routes + REMOTES map). Prompts for framework, language, Tailwind |
jorvel generate remote <name> --no-wire | Add a remote WITHOUT auto-wiring it into the host |
jorvel generate remote <name> --framework vue --lang js --tailwind | Skip prompts: Vue remote in JavaScript with Tailwind |
jorvel generate remote <name> --no-tailwind | Skip the Tailwind prompt (no Tailwind) |
jorvel generate wizard | Prompt-driven generator (framework + Tailwind per app) |
jorvel generate types | Emit the host's src/remotes.d.ts from its federation/routes wiring (so import('remote/App') type-checks) |
jorvel add remote <name> [--port n] [--url …] | Wire an existing remote into the host: federation map + route + remotes.d.ts + bootstrap REMOTES/NavLink |
jorvel add db [app] [--driver sqlite|libsql] | Scaffold a Drizzle ORM backend into an app: schema + client + migrations + seed + a defineLoader data module |
Naming rules
- App names must match
/^[a-z][a-z0-9-]*$/(lowercase, alphanumeric, hyphens; must start with a letter). - Ports must be in
1–65535; the CLI refuses duplicates and reserved ranges. - The host should be on a stable port (e.g.
3000) — generated configs reference it from every remote.
Dev & build
| Command | Purpose |
|---|---|
jorvel dev | Run all apps with the Rspack dev-server (colored per-app output; fails fast on duplicate and already-in-use ports — --no-port-check to skip) |
jorvel dev --only shell,dashboard | Run only the named apps (--exclude for the inverse) |
jorvel dev --proxy-remotes | Serve every remote under the host origin (recommended) |
jorvel dev --hmr-remotes | Cross-app HMR — host reloads when any remote recompiles |
jorvel build | Production build, host first then remotes |
jorvel build --app dashboard | Build one app |
jorvel build --compress | Emit .gz / .br alongside every static asset |
jorvel build --compute-sri | Hash remoteEntry.js for SRI; writes jorvel.federation.sri.json |
jorvel build --parallel | Build apps concurrently (they are independent — federation resolves at runtime) |
jorvel build --stats [path] | Write a JSON summary (apps, sizes, shared-dep conflicts) — default jorvel-build-stats.json |
jorvel image optimize [--app n] [--formats webp,avif] [--widths …] [--quality n] | Generate responsive/modern-format image variants from dist/ |
jorvel lazy | Scaffold a lazy-boundary helper for code-split remote components |
jorvel analyze --app dashboard | Open a bundle analyzer (rsdoctor → rspack-bundle-analyzer → built-in HTML fallback) |
jorvel perf-dashboard [--input file] [--budgets file] | Live terminal dashboard: remote loads, p95, size, budget status |
jorvel route-editor [--manifest file] | Emits a self-contained HTML editor for the host route tree (drag remotes onto a parent path). Defaults the manifest to the discovered host app. |
jorvel adapter add <vue|svelte|solid> --name X | Scaffold a remote built with a non-React framework |
jorvel split [--log file] [--top N] | Analyze a traffic log and suggest the highest-impact component to split into its own remote |
jorvel loadtest [--target url] | Scaffold a k6 load-test script with p95 / failure-rate thresholds |
jorvel typedoc [--out dir] | Generate the TypeDoc API reference from libs/* into the docs site (markdown by default) |
jorvel schema [--out dir] | Emit the authoritative JSON Schemas (jorvel.config / jorvel.app / jorvel.federation) re-sourced from @jorvel/types |
jorvel config validate | Validate jorvel.config.json against the bundled schema |
jorvel turbo [--force] | Scaffold a turbo.json with the standard JORVEL task graph (build / typecheck / test / lint / dev) |
jorvel federation | Regenerate jorvel.federation.json for every app |
jorvel federation diff [--base ref] [--allow-breaking] [--json] | Diff federation contracts vs a git base ref; exits 1 on a breaking change (removed expose, dropped remote, singleton demotion) — a CI gate |
jorvel canary <remote> --url … [--weight n] [--promote] [--rollback] [--status] | Weighted canary rollout for a remote → jorvel.federation.canary.json (runtime picks per user via pickWeightedRemote) |
jorvel federation impact [remote] [--json] | Impact analysis — which hosts consume a remote (before changing/retiring it) |
jorvel info [--json] | Shareable environment diagnostic bundle (OS, Node, pkg managers, apps, @jorvel deps) |
jorvel routes | Compile src/pages/ into src/jorvel.routes.ts (or .js for JS apps) |
jorvel routes --watch | Re-compile on file changes |
Typical dev session
bash
# Terminal 1
jorvel dev --proxy-remotes --hmr-remotes
# Terminal 2 — auto-regenerate routes when you add a page
cd apps/dashboard
jorvel routes --watchSSR
| Command | Purpose |
|---|---|
jorvel ssr export | Pre-render the routes table to static HTML (SSG) |
jorvel ssr export --out dist-ssg --manifest manifest.json | Custom output + content-hash manifest |
jorvel ssr serve --port 3000 | Streaming Node SSR (default) |
jorvel ssr serve --port 3000 --no-stream | Synchronous SSR — useful for buggy CDN edges |
jorvel ssr serve --static apps/shell/dist | Also serve built client assets so hydration bundles resolve |
Quality
| Command | Purpose |
|---|---|
jorvel lint | ESLint across the workspace; reuses the workspace config |
jorvel lint --fix | Apply auto-fixes |
jorvel test | Vitest across every package, parallel by default |
jorvel test --coverage | Generate HTML + lcov coverage under each coverage/ dir |
jorvel typecheck | tsc --noEmit per package, project-references aware |
jorvel perf | Bundle-size budget check; reads perf.budget.json |
jorvel e2e | Run Playwright against the example app |
Budget format
perf.budget.json takes pattern entries like { "*.js": { "maxSize": "200kb" } }. Patterns are matched against the emitted asset names; failing budgets exit non-zero so CI catches regressions.Ops
| Command | Purpose |
|---|---|
jorvel diagnose | Verify Node, pnpm, Rspack peer, ports, configs, .env vs .env.example, federation contract drift, React-duplication risks |
jorvel env check | Fail if any var listed in .env.example is missing |
jorvel env scaffold | Write a starter .env.example |
jorvel deploy --target vercel | Scaffold vercel.json + edge handler |
jorvel deploy --target cloudflare | Scaffold wrangler.toml + Worker handler |
jorvel deploy --target node | Scaffold a Node server entry |
jorvel deploy --target docker | Scaffold a multi-stage Dockerfile |
jorvel ci affected | List apps changed since the last commit — feed into a build matrix |
jorvel sw generate [--app <name>] | Write jorvel-sw.js into the host's public/ (auto-discovers the host app when --app is omitted) |
CI snippet
.github/workflows/ci.yml
yamljobs:
affected:
runs-on: ubuntu-latest
outputs:
apps: ${{ steps.affected.outputs.apps }}
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- uses: pnpm/action-setup@v4
with: { version: 9.15.5 }
- run: pnpm install --frozen-lockfile
- id: affected
run: echo "apps=$(jorvel ci affected --json)" >> "$GITHUB_OUTPUT"
build:
needs: affected
if: needs.affected.outputs.apps != '[]'
strategy:
matrix:
app: ${{ fromJSON(needs.affected.outputs.apps) }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with: { version: 9.15.5 }
- run: pnpm install --frozen-lockfile
- run: jorvel build --app ${{ matrix.app }} --compress --compute-sriWorkspace config
Every command loads a single jorvel.config.json from the workspace root (validate it with jorvel config validate). Key fields:
| Field | Effect |
|---|---|
appsDir | Directory the CLI scans for apps. Default "apps"; set it to relocate the apps folder — honored by app + host discovery across dev/build/routes/federation/deploy/ci/sw/route-editor. |
federation.shared | Extra packages to share as singletons across host + remotes (merged into every generated federation config). |
security | CSP / allowlist defaults consumed by the security helpers. |
deploy | Adapter target + options for jorvel deploy. |
plugins | CLI plugins loaded at startup. |
Environment variables
| Variable | Effect |
|---|---|
JORVEL_DEBUG=1 | Print full stack traces from CLI errors |
JORVEL_NO_COLOR=1 | Disable ANSI colors (also respects NO_COLOR) |
JORVEL_OFFLINE=1 | Skip network checks during scaffolding |
JORVEL_DEV_RELOAD_URL | Injected by --hmr-remotes; the host's reload-WS endpoint |
JORVEL_E2E=1 | Opt into the Playwright suite locally |
Exit codes
| Code | Meaning |
|---|---|
0 | Success |
1 | Generic failure (uncaught exception, validation error) |
2 | User input invalid (bad flag, missing argument) |
3 | Lifecycle failure (build/test/typecheck step exited non-zero) |
