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 (To take the current release anyway, pass
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:--min-release-age=0 on npm, or
exclude Vendo in pnpm-workspace.yaml: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 avendo/server.ts(.mjswithout atsconfig.json) holdingcreateVendo()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--agentplan asmount, andvendo doctorfails 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.jsonis regenerated by sync; the rest are stubs you own. .env.example.VENDO_BASE_URL=http://localhost:3000with 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/prebuildhooks inpackage.jsonsovendo syncruns alongside your dev and build.vendo syncis prepended when a hook already exists; existing formatting is preserved.
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
nextdependency): the catch-all route undersrc/appwhen that directory exists, elseapp. - Express (an
expressdependency):vendo/server.ts. Two manual steps remain, which init prints: mount the adapter withapp.use("/api/vendo", mountVendo())and wrap the client entry in<VendoProvider>.vendo doctorreports broken until both are done. - Everything else (
--framework custom, and the automatic landing for a host with neither dependency): a runtime-neutralvendo/server.ts— one exportedhandleVendoRequest(request, env)taking a webRequestand returning aResponse, 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.
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 readspackage.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. Thepredev/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):
/status round trip, and sends one real
model turn. vendo doctor --json is the machine-readable gate agents loop on.
See the CLI reference.