The CLI handbook
Everything you can do in the Vibes DIY web UI — and a good deal you can't —
is scriptable from the shell. There's nothing to install: every command runs
as npx vibes-diy <command>. This page is the tour by task; the
command reference is the complete flag-level contract,
generated from the CLI's own help output. For the story of building whole
sites with one command, see the generate case study.
Sign in once (or never, in CI)
shnpx vibes-diy login
opens a browser flow and enrolls this machine with a device certificate —
that cert is the credential for everything below; there are no API keys. For
headless environments (CI, containers), export the enrollment's keybag file
via the VIBES_DEVICE_ID env var instead — the exact recipe, including why
it's the keybag JSON and not a bare id, is in the
CI lane pattern.
Claim your handle
Signing in gets you an account; it does not get you a handle. Your handle
is the public name your apps are published under — vibes.diy/<handle>/<app> —
and nothing picks one for you, so the first push, publish, generate or
edit on a brand-new account stops and asks for one:
shnpx vibes-diy claim-handle # see suggestions — claims nothing
npx vibes-diy claim-handle potluck-pat # claim that name, and make it your default
Run with no name and you get a list of available handles (names derived from your profile first, random three-word slugs after) plus the command to claim one. Nothing is reserved until you type a name back — that's the point: the name is public and permanent-feeling, so it's worth choosing on purpose. If the name is already taken you're told so, and can just try another.
Claiming also sets the handle as your default, so every later command acts as it without any extra flag.
Act as a specific handle (--handle)
One account can hold several handles (your public you/… names). One is
your default — the identity every command uses when you don't say otherwise.
To act as a different one of your handles for a single command, pass
--handle <slug>:
shnpx vibes-diy db put --vibe you/potluck --db signups --handle you-bot '{"rsvp":"yes"}'
npx vibes-diy push --handle you-bot # publish under you-bot this once
--handle is stateless: it overrides the acting handle for that one
invocation only and never changes your saved default. (To change the default
itself — a persistent switch — use npx vibes-diy user-settings --set-default-handle <slug>.) The handle you pass must already be bound to
your account; you can't act as someone else's handle.
Every command that acts as an identity accepts it — push, edit, pull,
generate, put-asset, versions, publish, unpublish, and all db,
secrets, and developer subcommands. It's the clean primitive for CI or a
shared device that should write as a dedicated bot handle without disturbing
whoever's default is set on that machine.
Ship apps from the shell
shnpx vibes-diy system > RULES.md # the coding rules the generator follows
# write App.jsx (and optionally access.js, backend.js) …
npx vibes-diy push # deploy — prints a live HTTPS URL
Or skip the writing part entirely:
shnpx vibes-diy generate "a potluck signup with dish categories"
npx vibes-diy edit you/potluck "add a vegetarian filter"
generate opens a chat on the same lane as a first prompt on the web: the
server names the app and builds it. Then, by default, generate publishes it
the way a website publish does — reachable by anyone, or gated when the
app is one the build judged privacy-sensitive, with the app's own access rules
governing its documents either way. A build that has no access.js yet stays
private with a note, since nothing would govern what visitors may do with
its data; add an access.js and push, or pass --no-access-fn to open it
anyway. --private publishes it private instead — reachable only by you and
the people you approve — whether or not the app already existed. It then
stays in that conversation, printing the build's progress and writing each version of the
files to disk; in a terminal you can type a follow-up (/exit or Ctrl-D to
leave), and under --json it returns as soon as the build is done.
--record <dir> keeps a raw transcript of the run for debugging.
A new app's first build runs on our fastest builder (the Lightning build);
--careful has the agent plan the whole app first and build it on our most
capable model. edit sends
a follow-up prompt to an existing vibe, writes the changed files to disk, and
pushes live. Round-trip an app you already have with pull / push:
shnpx vibes-diy pull you/potluck --dir ./potluck # draft by default; --published for the live release
npx vibes-diy push # from that directory
Versions, publish, unpublish
shnpx vibes-diy versions you/potluck # every release: fsId, mode, seq — ● marks published
npx vibes-diy pull you/potluck --fsId <id> # retrieve any historical version
npx vibes-diy publish you/potluck # promote the latest draft to production
npx vibes-diy unpublish you/potluck # reversible takedown — code, data, grants all kept
Publishing only ever mints a new production release; it never destroys
history, and unpublish is a tombstone you can lift with publish. One
caveat that matters when testing: access.js and backend.js always run
the live release — old fsIds serve pinned pages, not pinned backends —
so stage risky backend changes under a secondary slug.
Pulling a specific version
versions prints the release list, and the version menu on your app's page
labels the same releases v1, v2, v3… pull --version speaks that label,
so the CLI and the web UI agree about which one is "v3" by construction:
shnpx vibes-diy pull you/potluck --version v3 # the version the menu calls v3
npx vibes-diy pull you/potluck --version 3 # the bare number works too
npx vibes-diy pull you/potluck --fsId <id> # an exact version, by id
npx vibes-diy pull you/potluck --published # the live production release
With no selector at all you get your latest draft — the newest thing you pushed, released or not.
Name a version that doesn't exist and the error tells you what does, instead of leaving you to guess:
Error: No version v9 of you/potluck. Available: v1 (v1 is the published head).
And two selectors together is an error, never a silent winner — the flag whose version you didn't want would otherwise be the file you start editing:
Error: Pick one version selector, not 2: --version and --published
(There is also a --draft selector. For your own vibes it does nothing you
don't already get, since the latest draft is the default; it exists so a
platform administrator doing support work on someone else's app has to opt in
explicitly to their unreleased work, because a bare pull of a foreign app
serves the published release.)
Suggestion chips on your app's card
The suggestion chips a visitor sees on your app's edit card are part of that published release — they're whatever your app last offered when you published, not whatever your chat said a minute ago. Set them yourself when you want specific invitations in front of strangers:
shnpx vibes-diy app chips you/potluck "Add a signup sheet" "Track who brings what"
npx vibes-diy app chips you/potluck --clear # show visitors no chips at all
Up to three chips (extras are trimmed). This changes what visitors see, not your own edit card, which keeps following your latest chat turn.
One thing to know: publishing the vibe again re-derives the chips from your chat and overwrites whatever you set by hand. Set your chips after you publish, and set them again after your next publish.
Changing an app's look after it is built
Two different things make up how an app looks, and they change at two different speeds.
Colours change now. A theme (and the style tweaks on top of it) is served
with the app, so saving one is the whole job — nothing is rebuilt. Visitors pick
it up on the next cache beat, within about ten minutes; add ?cb=1 to the app's
URL to see it at once.
Layout changes on the next build. Every app is also built with a layout archetype — the shape of the page — and three flourishes, the small touches on its controls and headings. Those live in the app's own code, so choosing new ones doesn't rearrange anything by itself: it tells the builder what to use next time. The very next edit you ask for restructures the app onto them, keeping your data and how the app works.
In the web editor, the Style tab starts with whole-style Presets and a Font dropdown, followed by colors and a spacing pad. Preview your changes, then use Publish style at the top to make them public; the same button reads Published once the draft matches the published style. Revert to saved restores that published style.
Below those controls, pick an archetype and exactly three flourishes, press Save layout, and then press Rebuild layout when you want the app rearranged right away rather than on your next edit. Some flourishes are greyed out — an app wearing a house look only offers the ones that look sits well with, and the one that rules it out is named. The theme picker is in Settings.
From the shell:
shnpx vibes-diy app look get you/potluck # theme, style, archetype + flourishes
npx vibes-diy app look set you/potluck --theme slab
npx vibes-diy app look set you/potluck --variety "card-grid:hover-lift,accent-rule,tint-wash"
npx vibes-diy app look set you/potluck --variety none # back to no chosen layout
npx vibes-diy app look set you/potluck --variety "list-feed:hover-lift,accent-rule,tint-wash" --relayout
app look get also tells you where the current layout came from: drawn for you
when the app was built, chosen at build time, or changed since. --relayout
is the one flag that builds something — it asks for the rearrangement
immediately, which spends a build the way any other edit does. Without it,
saving only arms the next one. npx vibes-diy variety prints the archetype and
flourish names with what each one does, and a name that isn't one of them is
refused before anything is written, with the valid names listed.
Your app's data is scriptable
shnpx vibes-diy list # your vibes
npx vibes-diy db list --vibe you/potluck # its databases
npx vibes-diy db query --vibe you/potluck --db dishes # latest docs
npx vibes-diy db get --vibe you/potluck --db dishes <docId>
npx vibes-diy db put --vibe you/potluck --db dishes '{"kind":"dish","name":"chili"}'
npx vibes-diy db del --vibe you/potluck --db dishes <docId>
npx vibes-diy db subscribe --vibe you/potluck --db dishes # live change tail
Attaching files to a document
db put can carry files along with the document. Each --file names a file or
a glob, and every match lands on the document as _files.<filename> — the same
attachments an app saves from the browser, with a URL your app can show:
shnpx vibes-diy db put --vibe you/potluck --db dishes \
'{"_id":"dish:chili","kind":"dish","name":"chili"}' --file chili.png
npx vibes-diy db put --vibe you/potluck --db dishes \
'{"_id":"dish:menu","kind":"menu"}' --file 'photos/*.jpg'
--files is the same flag spelled the other way. Anyone who can write the
app's data can attach files this way, not only its owner. Run it again and
files that haven't changed stay as they are — only new or edited files upload
— and attachments already on the document that you didn't name are kept. Each
file prints uploaded <name> or unchanged <name> as it goes. Images, text
and JSON attach on any account; other file types ask for a card on file first.
subscribe streams document changes as they commit — a real-time tail you
can pipe into anything. These commands are also how external workers join an
app's workflow — see
doc-status state machines.
Sample data
An app can ship sample records in a seed.json beside its code. They land in
the app's real databases when you ask for them — the same thing the Add
sample data button in the Data tab does, and what the builder can do for you
in chat:
shnpx vibes-diy db seed add you/potluck # add the live version's sample records
npx vibes-diy db seed remove you/potluck # take them out again
add keeps every record already there, including sample records you edited,
and adds the ones that are missing. remove takes the sample records out and
keeps them out until you add sample data again; records people added stay.
Both print what they did per database. Only the app's owner can run them.
Reading your own vibes, and reading someone else's
The read commands (get/query/list) behave differently depending on whose
vibe you name, and the split is worth knowing before it surprises you.
Your own vibes — including any vibe owned by any handle on your account — read with the owner's admin-mode override applied for you. That's why the CLI can show you a document your browser session can't: it takes the override lane your ownership already entitles you to. You never type a flag for this.
Someone else's vibe is read as you, with their app's access rules applied to you like any other visitor. If those rules don't let you see it, the read is refused:
$ npx vibes-diy db list --vibe mike/clone-arrange-luck-soft
Error: Access denied
(reading another owner's vibe: retry with --admin to request platform-admin elevation)
That hint is honest about what --admin is: a request, not a grant.
Adding it asks the server for platform-admin elevation, and the server honors
that only for the short, verified allowlist of platform administrators who do
support work. For everyone else the flag changes nothing — the same read is
refused with or without it. It is not a way to see more of somebody else's
app than they've shared with you.
Writes are honest by default, and db put --admin and db del --admin are
not the same override. Both bypass the older per-database ACL, but only
del will proceed past an access function that refuses the operation; a put
the access function refuses stays refused, --admin or not. That asymmetry is
deliberate rather than an oversight: a delete removes something, while a forced
write would put words in another person's mouth — a document attributed to them
that they never wrote. Every forced delete is audited.
The full story is in the access model.
Secrets, assets, transcripts
shnpx vibes-diy secrets set STRIPE_KEY --vibe you/potluck # backend-only, write-only
npx vibes-diy secrets ls --vibe you/potluck # names + last4, never values
npx vibes-diy secrets rm STRIPE_KEY --vibe you/potluck
npx vibes-diy put-asset ./hero.jpg # content-addressed upload — prints CID + public URL
npx vibes-diy codegen-log you/potluck # the builder↔LLM transcript that generated the app
npx vibes-diy app-chats you/potluck # the app's own runtime AI conversations
Secrets surface as ctx.secrets in backend.js.
put-asset returns an immutable, publicly served URL — handy for images your
vibes or blog posts reference. The two transcript commands answer different
questions: codegen-log is how this app got built, app-chats is what
the app's users asked its AI.
The CLI teaches you the platform
shnpx vibes-diy skills # list the codegen skill docs
npx vibes-diy skills backend # dump one — the same doc rendered at /docs/reference/
npx vibes-diy themes # the design themes
npx vibes-diy system # the base system prompt itself
These dump the exact documents the code generator reads — the same corpus published as the generator's reference, available offline in your terminal.
Mount your vibes into any AI agent
shnpx vibes-diy mcp
starts an MCP server (stdio transport) exposing list/get/put/query/delete
over your vibes' data, plus adding and removing an app's sample data — so Claude Code, Cursor, or any MCP-capable agent can
read and write your apps' databases with your device credential and your
access rules. npx vibes-diy mcp --help prints the client setup snippet.
Updated CLIs keep working as settings grow
Current CLI builds read the user-settings fields they understand and skip fields a newer server adds, so a server upgrade doesn't break settings commands. If a settings command fails right after a server upgrade, update the CLI first — builds older than this tolerance fix still hard-fail on fields they have never heard of.
Where to go next
- CLI command reference — every command and flag,
generated from
--help. - Generate: one sentence per app — the case study.
- Patterns cookbook — the CLI as the glue in production workflows.