CLI

Overview of the zpress CLI -- commands, the dev server, file watching, and the build pipeline.

Overview

zpress uses yargs for command routing and @clack/prompts for styled terminal output. The CLI entry point is in packages/cli/src/, which registers all commands. Each command is a standalone module that orchestrates the core sync engine and Rspress build APIs.

Commands

zpress has eight commands:

CommandDescription
syncRun the sync engine (config → .zpress/)
devSync + Rspress dev server + file watcher
buildSync + Rspress static build
servePreview a built site from .zpress/dist/
cleanRemove .zpress/cache/, content/, and dist/
setupCreate a starter zpress.config.ts
dumpResolve the full entry tree and print as JSON
generateGenerate banner and logo SVGs from project title

sync

zpress sync [--quiet]

Runs the sync engine once. Loads the config, resolves all entries, writes content to .zpress/content/, generates sidebar/nav JSON, and reports write/skip/remove counts.

This is the core operation that all other commands build on.

dev

zpress dev [--quiet] [--clean]

The primary development workflow. Combines three operations:

  1. Initial sync -- Full sync to populate .zpress/content/
  2. File watcher -- Monitors source directories for changes
  3. Rspress dev server -- Starts on http://localhost:6174 with hot module replacement

The --clean flag removes cache, content, and dist before starting.

File Watching

The watcher (packages/cli/src/watcher.ts) monitors:

  • Glob entries -- Parent directories of glob patterns (chokidar handles recursion)
  • Single-file entries -- Individual source files
  • Config file -- zpress.config.ts (triggers config reload on next sync)
  • Planning directory -- Optional .planning/ directory

Watch behavior:

  • Markdown file changes (add, change, remove) trigger a debounced re-sync (150ms)
  • Config file changes reload the config object for the next sync cycle
  • Duplicate watch paths are deduplicated (child paths under a watched parent are skipped)
  • Concurrent syncs are prevented -- if a sync is running, the next change queues a pending resync

build

zpress build [--quiet] [--clean]

Produces a static site:

  1. Optional clean step
  2. Full sync
  3. Rspress build (generates optimized HTML/CSS/JS in .zpress/dist/)

serve

zpress serve [--no-open]

Starts a static file server pointing at .zpress/dist/ on http://localhost:6174. The browser opens automatically; use --no-open to disable.

clean

zpress clean

Removes .zpress/cache/, content/, and dist/. Safe to run at any time -- all content is regenerated by sync/build.

setup

zpress setup

Creates a starter zpress.config.ts in the current directory if one does not already exist.

dump

zpress dump

Resolves the full entry tree from the config and prints it as JSON. Useful for debugging config resolution and glob patterns.

generate

zpress generate

Generates branded banner and logo SVG assets from the project title. Reads title and optional tagline from zpress.config.ts, generates SVGs, and writes them to .zpress/public/. Skips generation when no title is configured. Does not overwrite files that have been manually customized.

Rspress Integration

The CLI communicates with Rspress through packages/cli/src/rspress.ts:

FunctionPurpose
startDevServer()Launch Rspress dev server on port 6174
buildSite()Run Rspress static build to .zpress/dist/
serveSite()Start static file server for .zpress/dist/
openBrowser()Cross-platform browser launcher

All functions receive a Rspress config object built by createRspressConfig() from @zpress/ui. This config loads the generated JSON files (sidebar, nav, workspaces) from .zpress/content/.generated/ and wires up the zpress theme.

Command Lifecycle

zpress dev (detailed)

1. Parse args (yargs)
2. Create paths (.zpress/)
3. Load config (c12)
4. Clean (optional: remove cache/content/dist)
5. Run initial sync
   └── resolve entries → write content → generate sidebar/nav → save manifest
6. Create file watcher (chokidar)
   ├── Watch source directories from config
   ├── Watch config file for reloads
   └── Watch .planning/ (optional)
7. Start Rspress dev server (:6174)
8. On file change:
   ├── Debounce 150ms
   ├── If config changed → reload config
   ├── Re-sync (incremental, skips unchanged pages)
   └── Rspress HMR picks up content changes

zpress build (detailed)

1. Parse args (yargs)
2. Create paths (.zpress/)
3. Load config (c12)
4. Clean (optional)
5. Run full sync
6. Run Rspress build
   ├── Read content/ + .generated/ JSONs
   ├── Render with zpress theme
   └── Write optimized static site to dist/

Error Handling

CLI errors are handled at the command boundary:

  • Config errors -- defineConfig() exits with a descriptive message via process.exit(1)
  • Sync errors -- Result tuples propagate up; the CLI reports them via @clack/prompts
  • Rspress errors -- Build/dev failures are caught and reported

No command calls process.exit directly except through the config validation boundary. All user-facing error formatting is centralized in the CLI layer.

References