Skip to main content
Run init after installing the umbrella:
Bare npx vendo init is the path every quickstart takes, and its questions do the configuring. The flags exist so an unattended or agent-driven run can answer those questions without a prompt; Every flag lists them.
Right after a Vendo release, package managers with a release cooldown hold the new version back. pnpm 11 (minimumReleaseAge, one day by default) fails loud with “no versions available”; npm’s opt-in min-release-age instead resolves silently to the newest version old enough to pass, and vendo init pins that stale version in package.json. Check what you actually got:
To take the current release anyway, pass --min-release-age=0 on npm, or exclude Vendo in pnpm-workspace.yaml:
Init is a one-command scaffold. It scans the app with deterministic analysis, then writes everything it can and tells you the little that is left. There is no interview: an interactive run stops only for seven Enter-to-accept decisions (the detected auth preset, the Vendo Cloud starter-key offer, consent for the AI judgment pass, one aggregated review if that pass proposes a loosening, a zod bump when your pin is below 3.25, an uncertain theme slot, and a closing “star the repo?”), and --yes answers all of them. Theme is extracted automatically, auth is detected from package.json, and every file init writes is either generated (safe to regenerate) or a stub it never clobbers once you edit it. Init never writes to a file you authored: every file it creates is new and Vendo-owned, plus its own package.json hooks. Mounting the agent surface in your layout is the one step it hands back to you, printed as an exact paste.
Installing Vendo with a coding agent? Point it at the agent install playbook instead. This page describes the command; /agents is the step-by-step an agent follows, including which value flags to pass and how to gate on vendo doctor --json.

What init writes

  • The server surface. The composition: for Next.js a catch-all app/api/vendo/[...vendo]/route.ts, for Express a vendo/server.ts (.mjs without a tsconfig.json) holding createVendo() and a Node HTTP-to-fetch adapter. Generated only while absent and never overwritten.
  • No client file. Init never writes one. Mounting the provider in your app/layout.tsx — one import line plus wrapping {children} in <VendoProvider baseUrl="/api/vendo"> — is your paste: init prints it in a framed “ONE STEP LEFT” block naming the file and the exact lines, carries it in the --agent plan as mount, and vendo doctor fails with E-WIRE-004 (printing the same paste) until it lands. Nothing is printed when you already mount a Vendo provider. A host with its own components writes one "use client" file holding the registry and the provider, and mounts that instead — the registry carries component references, which cannot cross a Server Component boundary.
  • The .vendo/ contract. tools.json (extracted from your OpenAPI spec and routes), overrides.json, policy.json, brief.md, theme.json, theme.extracted.json (what the extractor read, kept beside the theme you own), and a gitignored .vendo/data/. tools.json is regenerated by sync; the rest are stubs you own.
  • .env.example. VENDO_BASE_URL=http://localhost:3000 with a comment on the trust semantics (dev trusts the request’s own origin; production fails loud without it set), plus a commented model-key line. The append is idempotent.
  • predev / prebuild hooks in package.json so vendo sync runs alongside your dev and build. vendo sync is prepended when a hook already exists; existing formatting is preserved.
When the scan detects Next.js server actions, init also generates a vendo-actions.ts registration map beside the route and wires it into createVendo({ serverActions }) — the first time, on the run that creates those files. After that they are yours: init never rewrites a file you already have, and it compares the map only by the keys it registers, so an action added later comes back as just the entries to paste (plus the serverActions line for a route that predates your actions), and vendo doctor fails E-WIRE-009 until you apply them. See Tools from your API for the runtime rules. On Express and custom-runtime hosts the <VendoProvider> wrap is yours the same way: init prints the exact import and wrap lines to paste.

How detection decides

Init makes two independent, dependency-based calls before it writes anything: which framework to scaffold, and which auth family to wire.

Framework

Init detects two frameworks by dependency and scaffolds only what applies:
  • Next.js (a next dependency): the catch-all route under src/app when that directory exists, else app.
  • Express (an express dependency): vendo/server.ts. Two manual steps remain, which init prints: mount the adapter with app.use("/api/vendo", mountVendo()) and wrap the client entry in <VendoProvider>. vendo doctor reports broken until both are done.
  • Everything else (--framework custom, and the automatic landing for a host with neither dependency): a runtime-neutral vendo/server.ts — one exported handleVendoRequest(request, env) taking a web Request and returning a Response, constructed lazily on the first request. Cloudflare Workers, Bun, Deno, Hono, and Lambda adapters all mount it in one line. See Edge runtimes for the wiring and the adapter rules.
Init checks next first, so an app with both dependencies gets the Next scaffold: framework detection precedence is Next.js over Express, and a host with neither lands on the custom scaffold. A non-interactive run (--yes or no TTY) with no detected framework still errors and asks for an explicit --framework rather than guessing on an agent’s behalf.
Monorepos: init targets the app package, not the repo root. Detection reads the package.json of the directory init runs in — or the one you point it at (npx vendo init apps/web). In a workspace repo the framework dependency lives in the app package, so that is init’s target, and the vendoai install itself goes into that workspace with your package manager (npm install vendoai -w apps/web, yarn workspace <app> add vendoai, pnpm --filter <app> add vendoai). Run vendo login, doctor, and sync from that same directory: login writes the minted key to .env.local in the current working directory, and doctor/sync read that directory’s .vendo/ and package.json.

Auth

Init reads package.json and detects one auth family: next-auth/@auth/* (authJs), @clerk/*, @supabase/*, or @auth0/*. In an interactive run a single detected family gets one [Y/n] confirm before anything is written; decline it, or have several or none detected, and init leaves principal unwired and prints the exact one-line auth: addition for your composition. Pass --auth <preset> to answer without the prompt. See Auth and principals for the presets and when to pick each.

The model key

createVendo’s model is optional; when you omit it, the runtime resolves one through the model credentials. Init does not scaffold a model file: instead it runs a key step. If a provider key is already set it says so; otherwise it offers a metered Vendo Cloud starter key inline: vendo login approves a code in the browser and the minted VENDO_API_KEY is appended to .env.local without touching your other keys — you never paste a key. (vendo cloud login <email> is the email-OTP fallback.) Init never fails on a Cloud error. Production always needs a real provider key.

Agent mode

--agent is read-only: it prints a JSON plan and writes nothing. The plan carries the detected framework, writes (every file init would create), codeChanges (their diffs), mount (the layout paste as structured data — file, lines, and what skipping it costs), edits (pastes for files that already exist, such as a route missing its serverActions wiring), manualSteps (the same pastes as printable lines), the deterministically extracted tools with warnings, and per-tool riskRecommendations. It is a plan, not a scaffolding step: running --agent alone writes no .vendo/ files, so vendo doctor will still report a missing install. Scaffold with vendo init --yes (below).

Non-interactive setup

For CI or an agent-driven run, --yes scaffolds without prompts. Every wizard question has a value flag, so nothing hangs:
--yes skips the interactive prompts (auth confirm, theme review, Cloud offer) and accepts the detected defaults, ending with an Agent tail: block naming the files this run left to hand-edit. Init rejects options it does not recognize and exits 1 before doing anything, so a flag an older CLI does not support can never be silently dropped.

Every flag

vendo init [dir]dir is the app to initialize, defaulting to the current directory.

Answering the wizard

--cloud-key and --byo answer the same question, as do --ai and --no-ai. Passing both halves of either pair exits 1.

Overriding detection

MCP door

Both only apply with --use-case mcp. Passing either without it exits 1.

Run behavior

--base-url is written to .env.example only, by replacing init’s own localhost placeholder. It never touches .env.local, where a production URL would repoint local dev’s discovery, callbacks, and credential forwarding at the deployed origin. See the CLI reference for vendo init’s place among the other commands.

Re-running init vs. sync

Init is safe to run again: it only writes what is still missing, so a rerun on an already-scaffolded app is a no-op except for anything you deliberately undid. Day to day you don’t re-run init at all. The predev/prebuild hooks it wired call vendo sync on every build, which is what keeps .vendo/tools.json current as your API changes. Re-run vendo init itself only when the detected surface changes in a way sync can’t scaffold for, for example adding Express to a Next app or turning on an auth provider. See vendo sync for what a sync run does. Starting over — or removing Vendo — has its own page: Uninstall / start over.

Verify

Init does not run a live turn: vendo doctor owns verification. Start your dev server (and finish any paste init printed):
Doctor checks wiring, makes one live /status round trip, and sends one real model turn. vendo doctor --json is the machine-readable gate agents loop on. See the CLI reference.