Skip to content
Zever
Home

CLI Reference

Flags-only toolkit shell with exact CLI invocations for every command.

9 min readEdit on GitHub

Scaffolding

zever new, zever add, zever generate, zever extract. See the command table.

Inspection

zever compile, check, breaking, fmt, doctor, config show, routes, explain, check-boundaries, graph. See the command table.

Database

zever db migrate, db rollback, db seed. See the command table.

zever is a flags-only toolkit shell. Every command has an exact CLI invocation; run zever --help for the grouped command map.

When to use: scaffold, inspect, run, migrate, and document a Zever project. When not to use: project code stays in Go and .zen; the CLI drives it, never hosts logic.

  • Install the CLI with the one-line installer (go install .../cmd/zever@vX.Y.Z also works from v0.7.2 on). See Installation:
Terminal window
curl -fsSL https://raw.githubusercontent.com/zenta-dev/zever/main/install.sh | sh
  • zever --help prints the grouped map (Scaffolding / Inspection / Runtime / Database / Operations).

Global flags apply to every command:

Terminal window
zever --quiet <command> # suppress hints/tips on stderr; errors still print
zever --no-color <command> # disable styled output
zever --json <command> # machine-readable JSON envelope (also ZEVER_JSON=1)
zever -V # print the CLI version (alias for --version)

zever --help --agent prints the command map in an agent-friendly form. Structured --json data is emitted by the inspection commands (compile, check, explain, doctor, routes, config show, graph, breaking, check-boundaries) plus outbox, upgrade, and uninstall; every other command emits a JSON error envelope on failure. doctor --json reports ok:false with a nonzero exit when any battery fails. Most commands that write files or touch the database (new, add, extract, generate *, db migrate, db rollback, upgrade, uninstall) accept --dry-run to preview without applying.

--no-color is also honored via ambient NO_COLOR / TERM=dumb. Guided prompts for one-shot commands: -i / --interactive (before or after the subcommand) or ZEVER_INTERACTIVE=1|true|yes enables huh prompts. zever <command> -h always prints flags without running anything.

Bare-command contract: bare zever (no subcommand, TTY or not) prints usage to stderr plus zever: missing subcommand and exits 1, so scripts never hang. All errors go to stderr; stdout stays clean for command output.

No resolver step: pick the command, pass flags, check the exit code.

Code Meaning
0 success
1 runtime error (message on stderr)
2 flag misuse (error on stderr, no usage dump)

--help output goes to stdout; errors and bare-invocation usage go to stderr.

Terminal window
zever --help
zever completion bash > /tmp/zever.bash
zever docs --dir /tmp/zever-docs
ls /tmp/zever-docs
echo exit:$?

Expected output:

grouped command map on stdout (Scaffolding / Inspection / Runtime / Database / Operations)
completion script at /tmp/zever.bash
one man page plus one markdown file per command under /tmp/zever-docs
exit:0

Schema loop example:

Terminal window
zever fmt --write schema/
zever check schema/
zever compile --out ./generated
echo exit:$?

Expected output:

fmt: normalized files listed, if any
check: silent on success
compile: per-backend output under ./generated
exit:0
Group Equivalent CLI
Scaffold zever new (battery picker adds beyond the log, router floor; --profile minimal|api|full presets)
Scaffold zever add <battery>[/<adapter>] (adds a battery to an existing project; zever add -h prints flags)
Scaffold zever generate
Scaffold zever generate tinker
Scaffold zever extract
Inspect zever compile (--check gates drift: exit 1 when committed output differs; runs go mod tidy when generated code imports modules go.mod lacks, skip with --no-tidy)
Inspect zever check
Inspect zever breaking
Inspect zever fmt
Inspect zever doctor
Inspect zever config show
Inspect zever routes
Inspect zever explain
Inspect zever check-boundaries
Inspect zever graph
Runtime zever serve
Runtime zever dev
Runtime zever queue:work
Runtime zever schedule:run
Runtime zever tinker
Database zever db migrate
Database zever db rollback
Database zever db seed
Operations zever outbox (status, dlq list, dlq requeue, dlq purge, purge; see Outbox Ops)
Operations zever uninstall (remove the zever and zever-lsp binaries; --dry-run, --keep-lsp, --yes/--force)
Operations zever upgrade (upgrade the zever binary to the latest release; --version, --check, --dry-run, --yes/--force)
Tooling zever completion <bash|zsh|fish|powershell>
Tooling zever docs --dir <dir>
Flag Effect
--quiet suppress hints/tips on stderr
--no-color disable styled output
--json machine-readable JSON envelope output (also ZEVER_JSON=1)
-V print the CLI version (alias for --version)
--dry-run preview file edits / SQL / removals without applying (where supported)
-i, --interactive guided huh prompts for one-shot commands
--batteries a,b zever new: extra batteries to scaffold beyond the floor (skips the battery prompt)
--profile minimal|api|full zever new: start-small preset (explicit --batteries add to it)
--check zever compile: verify committed output matches a fresh compile, write nothing (exit 1 on drift)
--no-tidy zever compile: print a hint instead of running go mod tidy when go.mod misses modules the generated code imports
--adapters b=a,... zever new: per-battery adapter overrides (implies the battery, skips its adapter prompt)
-y, --yes zever new: skip all prompts, scaffold floor plus flags only
--list-batteries zever new: print the battery/default-adapter table to stdout and exit
--module PATH zever new: Go module path for the new project (default: the app name itself)
--dir PATH zever new: output directory (default ./<name>)
--framework-version V zever new: depend on a published Zever version instead of a local replace directive
--force zever new: scaffold into a non-empty directory anyway
-h print flags without running

Adds one core battery to an existing project. Synopsis (exactly one positional, no prompting):

Terminal window
zever add <battery>[/<adapter>] [--adapter NAME] [--force] [--module PATH[@VERSION]] [--dry-run]

--adapter overrides the slash form, --force overwrites an existing wiring.go registration, --module names a plugin battery’s Go module (required for plugin batteries), and --dry-run prints the edits without writing them.

The adapter may be omitted (zever add cache selects config.Default()’s own pick, e.g. memory) or pinned explicitly (zever add cache/redis). Empty halves, extra slashes, and unknown batteries are errors. Run it from the project root (the directory holding go.mod); without one it fails.

Effects (two append-only edits, never overwriting hand-written code):

  • go.mod: adds require entries for the battery’s core and adapter modules at the version pinned by the framework require (falling back to the CLI’s built-in framework version). For local checkouts (a replace github.com/zenta-dev/zever => <local-dir> marker), matching local replaces are derived for both modules. Paths already required (any version) or already replaced are left untouched.
  • internal/app/app.go: splices in the adapter’s named import plus its Register() call (gofmt-normalized). Either half already present is skipped, so re-adding the same battery is a no-op. Fails if the file has no import block or no func New, scaffold it with zever generate server first.

zever add does not run go mod tidy, run it afterwards so go.sum catches up, then serve:

Terminal window
zever add cache/redis
go mod tidy
zever serve

Inspects and repairs the outbox dead-letter queue without starting the relay. Every subcommand takes --dsn and --table; without --dsn/--table the values come from environment variables (OUTBOX_DSN, OUTBOX_TABLE) plus environment overrides. --json gives machine-readable output on every one.

Command Effect
zever outbox status Relay counters (pending, processed, failed, last_error, stalled)
zever outbox dlq list [--limit N] Failed messages, oldest first (0 uses the adapter default page size)
zever outbox dlq requeue --id X Requeue one failed message, resetting its attempt count and lock
zever outbox dlq requeue --all Requeue every failed message
zever outbox dlq purge --id X Delete one failed message by id
zever outbox purge --before 168h Delete processed messages older than the given duration

--id and --all on requeue are mutually exclusive and exactly one is required. purge --before takes a Go duration and must be non-negative. dlq purge needs an adapter that implements outbox.Deleter; only db does, so an unsupported adapter reports does not support message deletion rather than deleting nothing. Run these from a deploy box with database access, not from every replica. Metrics, alert rules, and the full runbook are in Outbox Ops.

Removes the running zever binary (resolved via os.Executable(), symlinks followed) plus every zever-lsp binary found on PATH. Binaries only: projects, caches, profiles, and config are never touched.

Terminal window
zever uninstall --dry-run # print the removal plan, delete nothing
zever uninstall --yes # confirm without prompting
zever uninstall --keep-lsp --yes # leave zever-lsp in place

Without --yes/--force, a terminal gets a [y/N] prompt defaulting to No; without a terminal the command fails and prints the exact zever uninstall --yes re-run. On Windows the running binary cannot delete itself, so self-delete becomes a printed del "<path>" step while zever-lsp removals stay automatic. --json emits the machine-readable envelope instead of the human plan.

Upgrades the running zever binary to the latest stable release (or --version X for an explicit target). The current version is the compiled cliVersion; the default target comes from api.github.com/repos/zenta-dev/zever/releases/latest.

Terminal window
zever upgrade --check # print the available version, exit 0
zever upgrade --dry-run # print the upgrade plan, download nothing
zever upgrade --yes # confirm without prompting
zever upgrade --version v0.7.0 --yes

Versions compare with golang.org/x/mod/semver: an already-current target prints already current and exits 0, and a target older than the installed binary refuses the downgrade unless --version requested it explicitly. The runtime.GOOS/runtime.GOARCH asset (.exe suffixed on Windows) plus SHA256SUMS.txt downloads from the release, the asset is verified with crypto/sha256, and any mismatch or network error aborts before anything is replaced. POSIX installs atomically (temp file in the binary directory, chmod +x, rename over the running binary); Windows stages zever.new.exe beside the binary and spawns a detached cmd /C helper that moves it into place after our PID exits — restart the shell to complete. Confirmation follows the same TTY rules as uninstall; --json emits the envelope.

  • zever dev is local watch-only: it prints zever dev: watching <schemaDir> and <serverEntry> … (Ctrl-C to stop) to stdout and restarts the server entrypoint on change. Ctrl-C stops the watcher and the server. Never a deployment path.
  • zever tinker is dev-only: every start prints WARNING: Zever tinker is development-only: it evaluates arbitrary Go against a live container, so run it against a development database only. to stderr. The REPL talks to the real container via the per-project shim (project.tinker_entry, default cmd/tinker-shim; scaffold with zever generate tinker). Never point it at production data.
  • zever completion <shell> prints that shell’s completion script to stdout; redirect into the completions dir, e.g. zever completion bash > /etc/bash_completion.d/zever. The scripts complete dynamically: .zen files for the schema commands, the generate kinds, --backend (comma lists), --profile, --adapters (battery=adapter for new, battery or battery/adapter for build).
  • zever docs --dir <dir> writes one man page plus one markdown file per command into <dir>; build stripped release binaries with make build-release (-trimpath -ldflags="-s -w").
  • migrate / rollback mask the DSN (--dsn ***) in display and output.
  • Script against exit codes, not output text: 0 / 1 / 2 are the contract; hint wording may change (and --quiet suppresses hints).
  • Keep stdout parseable: errors never touch stdout, so pipes and $(...) capture stay clean.
  • dev and tinker never run in prod: dev is watch-only, tinker evaluates arbitrary Go. Gate both out of deployment images.
  • Pin the installed CLI version to the repo release; flag surfaces move with releases.
  • Bare zever exits 1: expected; it prints usage to stderr with zever: missing subcommand. Pass a subcommand or --help.
  • Exit 2 with no usage dump: flag misuse. Re-check flag spelling with zever <command> -h; only the error prints.
  • tinker warns on every start: by design, the dev-only warning goes to stderr each launch. Do not silence it; do not aim it at prod data.
  • dev does not restart on edits: it watches the schema dir and the server entrypoint only. Edits outside those paths need a manual restart.
  • Styled output garbles CI logs: pass --no-color or set NO_COLOR=1; TERM=dumb is honored the same way.
  • zever outbox reports empty counters: the resolved --table does not match the table the relay writes. Compare against OUTBOX_TABLE environment variable.
  • zever outbox dlq purge says the adapter does not support deletion: only the db adapter implements outbox.Deleter. Switch the connection, not the command.