CLI reference
Every vantage command. dev, build, preview, check, routes, add, docs, search, doctor, upgrade.
vantage is the only CLI an app author uses. Run it from the project root unless noted.
Commands
| Command | Role |
|---|---|
vantage dev |
Dev server (HMR + optional API). Default :5173 |
vantage build |
Build client + optional server → dist/ |
vantage preview |
Run the production build locally (fullstack default :4173; spa via Vite preview) |
vantage check |
Static checks (routes, boundaries, forbidden files). Exit 1 on error |
vantage routes |
Print the page + API URL map (--pages / --apis for one side only, --detail for each route’s spec) |
vantage add <kind> <name> |
Scaffold or place a page / api / ui / block / skill / agents (--force to overwrite; skill scans for copies already placed and skips them, --dir picks the destination) |
vantage docs [name] |
Show the bundled guide and component reference |
vantage search <query> |
Search that same reference in full text (natural language or --regex) |
vantage doctor |
Diagnose environment / installation health |
vantage upgrade |
Regenerate artifacts and sync a placed AGENTS.md from the canonical copy |
Quick mode (pass a path directly)
Instead of cd-ing in before running a command, you can pass a project path directly. When the
first argument isn’t a known command but points at a filesystem path, Vantage starts dev with that
path as the root (printing quick dev → <path>).
vantage ./demo # folder → run dev inside it
vantage ./demo/index.tsx # page file → the folder holding its package.json
vantage ./demo/src/index.tsx # same with a src/ layout (the root is ./demo)
Path resolution rules:
| Path you pass | Root that’s used |
|---|---|
| A directory | the directory itself |
A .tsx / .jsx page file |
the nearest directory above it with a package.json (its parent otherwise) |
| A missing path / anything else | none (Unknown command error) |
Every root-scoped command except add, docs and search may also take a trailing path positional. You can spell out
dev, or pass the same path to build / check / routes, etc.
vantage dev ./demo # explicit quick dev
vantage build ./demo # build ./demo
vantage check ./demo/index.tsx # a file argument still checks its parent directory
vantage routes — the URL map, with specs
With no flags it prints the URL map of pages, layouts and API routes. Flags narrow it to one side or add the static spec of every route.
| Flag | Meaning |
|---|---|
--pages |
Pages only (plus layout / 404 / error) |
--apis |
API routes only |
--detail |
Add each route’s spec (pages: path params + definePage metadata; APIs: methods, request, response) |
--json |
Machine-readable output (with --detail, every entry gains a spec) |
--pages and --apis are not exclusive — passing both, or neither, prints everything.
vantage routes --pages # pages only
vantage routes --apis --detail # APIs with their specs
vantage routes --detail --json # machine-readable, specs included
Pages
/sales/:customerId sales/[customerId].tsx
title Customer detail
params :customerId
API
/api/customers/:id server/api/customers/[id].ts
GET
path :id
response 200 application/json
error 404 "Customer ${params.id} not found"
--detail reads these shapes:
| Line | Where it comes from |
|---|---|
title / nav / desc |
String literals in definePage({ ... }) |
params |
[id] / [...rest] in the filename |
| Method | HTTP method exports such as export function GET |
query |
searchParams.get/getAll/has("x") |
body |
request.json() / formData() / text() (plus the keys of const { a, b } = await request.json()) |
response |
Status, content type and object-literal keys of Response.json(…) / json(…) / new Response(…) |
error |
new HttpError(status, "message") |
vantage docs — read the docs from the CLI
The content of this site is bundled into the package, so vantage docs prints it as plain
Markdown. No network and no browser, which makes it the fastest way for a coding agent to check
props.
vantage docs # list every page (guide + components)
vantage docs button # show one page (short name → ui/button)
vantage docs parts/data-table # full slugs work too
vantage docs --all # concatenate every page
| Flag | Meaning |
|---|---|
--list |
List page names only (no body) |
--all |
Concatenate every page |
--json |
Machine-readable ({ slug, title, description, section, content }) |
--lang <ja|en> |
Language (default ja) |
With no argument, vantage docs lists slugs and descriptions by section — the left column is what
you pass back in.
$ vantage docs --lang en
Guide
index A config-free React dashboard framework. You only write index.tsx.
getting-started From install to running your first Vantage app.
routing Dropping a file creates a route. Conventions for pages, layouts, dynamic params, and 404/error.
…
@squadbase/vantage/ui
ui/accordion A stack of headings that open and close. One at a time by default.
ui/alert An in-page notice that flags something while the content is still shown.
ui/badge A small label for counts, states and tags.
…
vantage docs <name> show one page --json machine-readable
vantage docs --all show every page --lang ja | en
Pass a name and the page prints as Markdown (headings and quotes are coloured on a TTY, plain when piped). Prop tables stay readable as Markdown tables.
$ vantage docs button --lang en
# Button
> The button, with six variants and eight sizes.
The component you'll reach for most. `variant` carries the meaning, `size` the scale.
```tsx
import { Button, buttonVariants } from "@squadbase/vantage/ui";
```
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `variant` | `"default" \| "secondary" \| …` | `"default"` | Look and meaning. |
| `size` | `"default" \| "xs" \| "sm" \| …` | `"default"` | Height and padding. The `icon` sizes are square. |
| `render` | `ReactElement` | | Render as a different element (Radix's `asChild`). |
…
Names resolve from their short form: vantage docs button finds ui/button, and
vantage docs data-table finds parts/data-table. An ambiguous or unknown name prints candidates and
exits 1.
$ vantage docs sele
✗ No page named "sele". Did you mean: ui/select, parts/multi-select, parts/searchable-select?
--json is one page, machine-readable; content holds the whole Markdown body.
{
"slug": "ui/badge",
"lang": "en",
"title": "Badge",
"description": "A small label for counts, states and tags.",
"section": "components/ui",
"sectionTitle": "@squadbase/vantage/ui",
"content": "# Badge\n\n> A small label for counts, states and tags.\n\nA small label to sit beside…"
}
Links in the body are slugs, so [DataTable](parts/data-table) opens with
vantage docs parts/data-table.
vantage search — find it without knowing its name
vantage docs <name> assumes you know the name. When you’re coming from what you want to build —
“I need a UI for picking a date range” — use vantage search. It indexes the same bundled docs
(the guide plus every ui / parts / markdown component), and every result is a name you can hand
straight to vantage docs <name>.
vantage search date range filter --lang en # natural language (quotes are optional)
vantage search "pagination" --lang en
vantage search "enable[A-Z]\w+" --regex # sweep prop names with a regular expression
vantage search chart --limit 3 --json # machine-readable
| Flag | Meaning |
|---|---|
--regex |
Treat the query as a regular expression (case-insensitive) |
--limit <n> |
Results to show (default 10) |
--json |
Machine-readable output |
--lang <ja|en> |
Language (default ja) |
The default mode is BM25 full-text search. Names, titles and descriptions weigh more than body prose, and each hit shows the passage that matched. Japanese is segmented at script boundaries (kanji / katakana / hiragana), so a whole sentence works as a query.
$ vantage search date range picker --lang en --limit 3
parts/date-range-picker DateRangePicker · @squadbase/vantage/components
> A date-range picker with presets.
ui/calendar Calendar · @squadbase/vantage/ui
[`DateRangePicker`](parts/date-range-picker) gets you there faster than using this
components Components · Components
| [`DateRangePicker`](parts/date-range-picker) | Date range with presets |
The left column is the slug to hand to vantage docs <name>, the right one is the title and where it
is imported from, and below each is the matching passage. The real output also prints a
11 results for "…" en · bm25 header and a footer with what --limit hid (elided above). The count
is how many pages matched at least one term, so the tail is mostly irrelevant — read the first few
and raise --limit only if they miss.
--json is the same result set, machine-readable. score is the BM25 score and command is ready to
run (below: vantage search pagination --lang en --limit 1 --json).
{
"query": "pagination",
"mode": "bm25",
"lang": "en",
"count": 4,
"results": [
{
"slug": "parts/data-table",
"title": "DataTable",
"description": "The TanStack Table–backed table: sorting, search, pagination, selection.",
"section": "components/parts",
"sectionTitle": "@squadbase/vantage/components",
"command": "vantage docs parts/data-table",
"score": 5.404,
"snippet": "> The TanStack Table–backed table: sorting, search, pagination, selection."
}
]
}
--regex scans names, titles, descriptions and bodies, and prints matching lines with line
numbers — the mode to reach for when checking how a prop is spelled across pages.
$ vantage search "enable(Sorting|Filtering)" --regex --lang en
parts/data-table DataTable 4 matches
30 | `enableSorting` | `boolean` | Sort by clicking a header. |
31 | `enableFiltering` | `boolean` | Put a search box in the toolbar. |
50 <DataTable columns={columns} data={data} enableSorting enableFiltering>
Only the first 3 lines of a page are printed, but the 4 matches count is exact. A page that matched
on its name, title or description alone is marked name match and prints no body lines. Finding
nothing is not an error (exit code 0, "count": 0 with --json); only an invalid regular expression
exits 1.
--json
check / routes / doctor / build / upgrade / docs / search accept --json, useful for CI and agent
automation.
vantage check --json
{
"code": "ROUTE_CONFLICT",
"severity": "error",
"message": "2 files resolve to /sales",
"files": ["sales.tsx", "sales/index.tsx"],
"fix": "Rename or remove one route file so each route is unique."
}
build --api-base-url
vantage build accepts --api-base-url to set the base URL the client uses to call /api. Use it
when deploying the client and server on different origins.
vantage build --api-base-url https://api.example.com
The flag takes precedence over PUBLIC_API_BASE_URL from .env. Unset means empty (same-origin
relative paths). See Build & deploy for details.
--port — the dev / preview port
vantage dev (default :5173) and vantage preview (default :4173) accept --port.
vantage dev --port 3000
vantage preview --port 8080
An explicit --port is exact: if the port is taken, the server does not start and the command
exits 1. Writing --port 3000 means the port is a contract with something outside the process — a
reverse proxy, a container port mapping, an OAuth redirect URI — so quietly binding 3001 instead is a
silent failure, not a recovery (a supervisor that only checks “is anything listening on 3000” will
happily report a server nobody can reach).
Without --port, a busy default port still walks to the next free one, so running several
projects side by side takes no ceremony. Two flags override that default:
| Flag | Meaning |
|---|---|
--strict-port |
Fail instead of walking, even when the port came from the default |
--no-strict-port |
Walk to the next free port, even when --port was explicit |
vantage dev --port 3000 --no-strict-port # 3000 busy → starts on 3001
vantage dev --strict-port # will not start unless 5173 is free
Browser output in dev — forwarding and the overlay
vantage dev forwards what happens in the browser to the dev terminal. By default that means
console.warn / console.error plus uncaught errors and promise rejections.
1:46:34 PM [vite] (client) [console.warn] rows is empty
1:46:34 PM [vite] (client) [Unhandled error] TypeError: rows.map is not a function
> src/sales/index.tsx:12:18
11 | const rows = data?.rows
12 | return <ul>{rows.map((r) => <li key={r.id}>{r.name}</li>)}</ul>
| ^
Uncaught errors are source-mapped and printed with a code frame around the offending line, so most issues can be chased without opening DevTools. Nothing to configure, and no option to turn it off.
console.log / console.info are not forwarded: a log that runs on every render would bury the
server’s own output. Use console.warn for anything you want to see in the terminal.
The full-screen error overlay the browser shows on a runtime error can be hidden with
--no-overlay.
vantage dev --no-overlay
Use it when the overlay is in the way rather than helpful — screenshots and demos, or when the
error already reached the terminal and you want to look at the page underneath. On by default
(--overlay states it explicitly).
VANTAGE_PROFILE — measure before you tune
Set VANTAGE_PROFILE=1 on any command to see how long each phase took.
VANTAGE_PROFILE=1 vantage dev
[vantage:profile] scan 1.6ms @0.146s
[vantage:profile] diagnostics 2.1ms @0.148s
[vantage:profile] generate 1.5ms @0.159s
[vantage:profile] vite:createServer 16.2ms @0.165s
[vantage:profile] vite:listen 41.3ms @0.206s
The left column is the duration; @ is the time since the process started. The
phases are scan (route discovery), diagnostics (the static checks),
generate (writing .vantage/), vite:*, and build:client / build:server.
Static diagnostics (check)
vantage check detects these eight diagnostics (six errors, two warnings).
| Code | Severity | Meaning |
|---|---|---|
FORBIDDEN_FILE |
error | A forbidden config file exists at the root |
SRC_DIR_SPLIT |
error | src/ exists but pages or styles.css were left at the project root (or src/server/ exists) |
ROUTE_CONFLICT |
error | Two files resolve to the same route |
MISSING_DEFAULT_EXPORT |
error | A page has no default export |
INVALID_API_EXPORT |
error | An API exports no valid HTTP method |
CLIENT_IMPORTS_SERVER |
error | Client code imports from server/ |
SUSPICIOUS_ROUTE_DIR |
warning | A scaffolding-looking directory (pages/, app/, utils/, …) shows up in a URL |
PUBLIC_ENV_MISUSE |
warning | Client reads a non-PUBLIC_ env variable |
None of them import or run your code — the checks are purely static.
Build output
Inside dist/:
dist/
├── client/ Client (index.html + hashed assets)
├── server/index.mjs Only when server/ exists
└── vantage-manifest.json Deploy contract (mode: "spa" | "fullstack")
vantage preview reads the mode in vantage-manifest.json to decide between starting a Node
server or serving a static preview. Deployment is covered in detail in
Build & deploy.
Done
That’s the end of the app-author guide. Start from the smallest index.tsx and add pages, APIs, and
UI as you need them.
To hand those procedures to an AI agent, place the bundled Agents and Skills
with vantage add skill, and place the app map AGENTS.md with vantage add agents.