@vendoai/vendo owns the vendo bin — installing that one package is all it takes. The vendoai alias re-exposes it, so npx vendoai@latest … runs the CLI before anything is installed. vendo --version prints the version, vendo --help the command list.
init, login, doctor, sync, and knowledge reject an option they do not recognize and exit 1 before doing anything; a value flag missing its value fails the same way. mcp, cloud, and config do not check their flags — an unrecognized option is ignored there, though an unrecognized sub-command still exits 1.
vendo init
.vendo/ contract. Any error exits 1.
Init never writes to a file you authored. Mounting <VendoProvider> is the one paste it hands back, printed as an exact block naming the file and lines.
dir defaults to the current directory. In a monorepo, point it at the workspace whose package.json declares the framework dependency.
Answering the wizard
--posture broker exits 1 on a dev URL that is not https://. Vendo Cloud registers that origin as the tenant’s forwarding address and refuses a non-https one, so the door would be written and then fail on its first request. Take --posture local: zero config, and it works on http. The rest of the rule.
Overriding detection
Run behavior
--cloud-key and --byo answer the same question, as do --ai and --no-ai and --check and --no-check. Passing both halves of a pair exits 1.
--ai-polish is the older spelling of --ai and still works.
With no answers on the command line, --agent prints one JSON object of the questions it still needs, writes nothing, and exits 0. Your agent relays them to you, then re-runs init with your answers as flags — that run writes. Pass every answer on the first call and there is no ask pass at all. Full shape on Agent mode.
The full walkthrough is on vendo init.
vendo login
Claims a Vendo Cloud key through the claim ceremony. The CLI prints a pairing code and approval URL, then polls until a human approves in the browser.
The minted VENDO_API_KEY is written to .env.local in the current working directory and never printed. Run it from the same directory you ran init in.
The pending claim persists to ~/.vendo/pending-claims/<hash>.json (mode 0600, inside a 0700 directory), hashed from the directory the claim was opened for. A fresh vendo login in that same directory resumes the claim after a crash, and scoping by directory is what stops two logins in two projects from resuming each other’s ceremony. A pre-0.4.2 ~/.vendo/pending-claim.json is migrated on first read, and only when its recorded directory matches.
--wait takes a whole number of seconds; anything else exits 1. The command takes no email, and --email is not a flag.
vendo cloud device-login runs the same ceremony under an alias, with one difference: it does not check its flags, so an option it does not recognize is ignored rather than exiting 1.
vendo doctor
Reads the repo and reports what is wired and what is missing: wiring markers, the .vendo/ files, store persistence, surface ownership, the model credential in your environment, the tool catalog, installed ai and zod versions, and the MCP discovery files.
Doctor never starts a server and never makes a request. Run it with your app stopped.
It fails unless a visible surface is mounted somewhere. <VendoProvider> alone renders nothing a user can reach.
The
--json object is { vendo, version, wired, exit, checks, cloud, summary }. wired is true when no check failed, and exit is wired ? 0 : 1.
Exit codes
Every check’s symptom, cause, and fix is on its own troubleshooting page.
vendo sync
Runs the build-step scan manually: tool extraction, remix baselines, the host component catalog, and the theme.
Sync fails soft. An extraction failure still exits 0, because a sync problem must never break a build.
The
--json object is { ok, exitCode, report, impact, notes, theme, baselines, components }. An error field appears when extraction itself failed soft.
Exit codes
The theme re-scan
Sync re-runs the deterministic theme scan and reconciles it with.vendo/theme.json against the merge base in .vendo/theme.extracted.json. Hand edits are never clobbered.
A slot is machine-owned only when the base records it and theme.json still holds exactly that value. Everything else is pinned to you and reported with both values.
Values compare by meaning, not bytes: #FFFFFF and #ffffff are the same color.
Derived slots follow their source. accentText is the accent’s contrast color, headingFamily inherits fontFamily, and radius.small and radius.large scale from radius.medium.
The base advances only on a run with no pinned slots. --theme-refresh takes every changed slot and records the base.
What reaches Vendo Cloud
A baseline file that exists but cannot be read is skipped with a warning and its Cloud row is left alone. Only an absent file is a deletion signal.
What crosses the wire is the captured source: each component, every module in its import closure, and the app-root stylesheets. Capture stops at
node_modules.
The judgment pass
A coding agent grades each tool with a verbatim source quote behind every proposal, an independent skeptic checks each one, and the survivors land in.vendo/judgments.json.
Candidates are chosen by drift, a changed srcHash or a binding mismatch, unless --full judges everything. Hardenings and prose apply themselves; loosenings wait for a human.
.vendo/overrides.json is never written by this pass. It means one thing: what a human decided.
Non-interactive means CI, a pipe,
--json, --yes, or a run started by a package script. A run you did not invoke never gets a question.
On an incremental run
--ai skips the engine sweep, because predev calls sync on every dev-server start. The pass then reads the environment only, so a machine whose sole credential is a claude or codex CLI login gets judgment: structural-only. Add --full, or drop --ai on an interactive run, to walk the whole ladder.Sample run
vendo knowledge
add, list, and remove only edit .vendo/knowledge.json. sync is the one verb that moves content.
The manifest is written last, after the engine confirms, so a failed sync re-syncs instead of silently skipping.
vendo mcp
Tooling for publishing your door to the official MCP registry. Both subcommands operate on the current directory unless you pass a dir.
vendo mcp server-json
server.json the registry expects, reading name, version, description, and homepage from your package.json.
vendo mcp verify-domain
It prints both the DNS TXT record and the HTTP challenge value (
v=MCPv1; k=ed25519; p=<base64>). Publish either one.
vendo cloud
Client for the public Vendo Cloud API. Read results print as JSON.
--org and --project can be omitted when there is exactly one candidate.
There is no validate subcommand and no deploy subcommand. Key problems surface on the first real call, and automations need no deploy step of their own — they run in your process, woken by Cloud’s heartbeat on
POST /api/vendo/tick.
vendo cloud usage answers with per-day counts and the period total:
vendo config
Reports which layer owns each .vendo/ content surface. It reads local disk only: no credential, no network call.
Surfaces:
design-rules.md, brief.md, theme.json, policy.json, overrides.json. Each resolves as a value passed to createVendo, then the local file, then unset — see the content surfaces. A value passed in code wins over the file but is invisible to the CLI, so status only ever reports file or unset.
.vendo/overrides.json gates both app generation and tool enablement. Enablement resolves boot-once on the first request, so an edit applies on the next restart; generation picks it up per generation.
Retired commands
Both still parse and exit
1 with a line pointing at the replacement.
Agent surfaces
Machine-readable entry points, for a coding agent driving the install.Telemetry opt-out
SetVENDO_TELEMETRY_DISABLED=1, or set "optedOut": true in ~/.vendo/telemetry.json. DO_NOT_TRACK, CI, and production runtime also disable build and development telemetry.