CLI Reference

Complete reference for all DevOur CLI commands.

For installation and initial setup, see the CLI Setup guide.

How Commands Find Your Project

Commands that take an optional [projectId] use, in order:

  1. The project ID you pass
  2. The id in your configuration file: the --config path, or devour.json, devour.yml, or devour.yaml in the current directory
  3. A list of your projects to pick from

devour setup also accepts a project name in place of the ID.

Non-Interactive Use

When an AI agent or a CI pipeline runs the CLI, set DEVOUR_NON_INTERACTIVE=1. Setting CI has the same effect. With it set:

These still ask a question, so give them what they need up front:

Authentication Commands

setup-key

Save your DevOur API key.

devour setup-key

The CLI prompts for your API key, checks that it is 64 characters long, and stores it in your system's user configuration directory. Every command uses the saved key and asks for one when none is saved. devour theme upload also accepts --api-key or the DEVOUR_API_KEY environment variable.

logout

Remove the saved API key.

devour logout

Project Commands

ls

List your projects, oldest first, as ID - name.

devour ls

create

Create a new project.

devour create [name...]

Arguments:

ArgumentDescription
nameProject name (supports spaces)

Options:

OptionDescription
--config <path>Take the project name from this configuration file
--name <name>Project name

The name comes from --config, then --name, then the arguments, then the name in a configuration file in the current directory. Otherwise the CLI asks for it. create prints the new project's ID and sets only its name. To create a project and apply a whole configuration file in one step, run devour setup --config with a file that has no id.

Examples:

devour create
devour create "My Project"
devour create --name "My Project"

setup

Apply a configuration file to a project, or update its settings one at a time.

devour setup [projectId]

Arguments:

ArgumentDescription
projectIdTarget project ID or name (optional)

Options:

OptionDescription
--config <path>Apply this configuration file
--ignore-configIgnore the configuration file in the current directory
--key <key>Update a single setting
--value <value>New value for --key (the CLI asks for it when omitted)
--yesApply deletions without asking
--allow-data-lossAlso allow deleting collections that still hold entities

setup runs in the first mode that matches:

  1. With --config, it applies that file.
  2. With --key, it updates that one setting.
  3. When a configuration file is in the current directory and you didn't pass --ignore-config, it applies that file.
  4. Otherwise, it opens an interactive menu of the project's settings.

Applying a Configuration File

When the file has an id, setup updates that project: its settings, logo, Firebase service account, collections, forms, plans (products), pages, navigation, and locales. A form in the file updates the server form with the same id, or with the same name when it has no id. Any other form is created.

When the file has no id, setup looks for a project with the same name. If one exists, it asks whether to update it. Otherwise, or if you decline, it creates a new project. It then writes the project's id into the file. Run devour sync afterwards so the next setup has a synced base to compare against.

Examples:

devour setup
devour setup --config devour.json
devour setup --config devour.json --yes
devour setup --key colorMain --value "#3B82F6"
devour setup my-project-id --ignore-config

sync

Pull a project from the server into a local configuration file.

devour sync

Options:

OptionDescription
--config <path>Path to configuration file
--overwriteUse the remote value wherever local and remote differ
--newReplace the local settings with the remote ones
--localKeep local values and fill in what's missing from remote
--jsonWrite the file as JSON (devour.json)
--yamlWrite the file as YAML (devour.yml)

sync writes:

Without --overwrite, --local, or --new, sync asks you to choose the local or remote value for each setting that differs.

sync only reads from the server. To send your edits, run devour setup.

With --json or --yaml, when your current file is in the other format, sync writes a new file and asks whether to delete the old one.

Examples:

devour sync
devour sync --overwrite
devour sync --local
devour sync --yaml
devour sync --config custom-config.json

Config Stash Commands

Stashes keep your local edits while you refresh a configuration file that has fallen behind the server:

devour stash
devour sync
devour stash pop
devour setup --config devour.json

stash

Save the current configuration file's contents.

devour stash [-m <message>]
OptionDescription
-m, --message <text>Description for this stash
--config <path>Path to configuration file

Stashes are stored in .devour-stash.json next to the configuration file.

stash pop

Re-apply the most recent stash onto the configuration file and remove it from the stash list.

devour stash pop

Stashed values replace current ones. Nested objects are merged key by key, and lists such as collections or pages are replaced as a whole.

stash list

List saved stashes as stash@{n}: message (date).

devour stash list

Version Commands

version create

Create a new version of a project. A version is required before you can build and download a bundle.

devour version create [projectId]

Options:

OptionDescription
-v, --version <v>Version to create (defaults to the current version's next patch)
--config <path>Path to configuration file

Versions follow semantic versioning: MAJOR.MINOR.PATCH. Without --version, the patch number goes up by one, so 1.0.0 becomes 1.0.1.

Examples:

devour version create
devour version create my-project-id
devour version create --version 2.0.0

version bundle

Build the downloadable bundle for a version.

devour version bundle [projectId]
OptionDescription
-v, --version <v>Version to bundle
--config <path>Path to configuration file

Without --version, the CLI lists the versions and marks the ones that already have a bundle. If the bundle already exists, the command says so and changes nothing.

version delete

Delete a version.

devour version delete [projectId]
OptionDescription
-v, --version <v>Version to delete
--config <path>Path to configuration file

Without --version, the CLI lists the versions to pick from. It always asks for confirmation.

version reset

Reset the project to a version, discarding the changes made since.

devour version reset [projectId]
OptionDescription
-v, --version <v>Version to reset to
--config <path>Path to configuration file

Without --version, the CLI lists the versions to pick from. It always asks for confirmation.

Download Commands

fetch

Download a project bundle and extract it into the current directory.

devour fetch [projectId]

Options:

OptionDescription
-v, --version <v>Version to download (defaults to the version in your configuration file, then the latest)
--config <path>Path to configuration file

Behavior:

Examples:

devour fetch
devour fetch my-project-id
devour fetch --version 1.0.0

After Downloading:

docker compose up -d --force-recreate --build

Form Commands

form create

Create a form. The CLI asks for its name and submit button label, then lets you add sections and fields.

devour form create [projectId]

form edit

Open a form's layout to add, change, or remove its sections and fields.

devour form edit [formId]

formId accepts a form ID or name. Without it, the CLI lists the project's forms to pick from.

form list

List the project's forms.

devour form list

form delete

Delete a form after confirmation.

devour form delete [formId]

Theme Commands

theme create

Create a new theme from the starter template.

devour theme create [name]

The name is converted to kebab-case, and the CLI asks for it when omitted. The theme is created in the current directory. Inside a DevOur project directory, it is created next to the project instead, and the project's configuration file gets its theme set to the new theme. The CLI then prints the next steps.

theme validate

Check a built theme against the component contract.

devour theme validate [path]

path defaults to the current directory. The theme needs a package.json with a name, a version, and an author (the package scope or the author field), @devourapp/components installed, and a build in dist/. The command reports how many required components the theme implements and lists the ones that fall back to the default theme.

theme upload

Upload a theme to DevOur.

devour theme upload <path>

<path> is a prebuilt .zip or a theme project directory. Given a directory, the CLI packages the built files from dist/ with the name, version, and author from package.json. Build the theme first.

OptionDescription
--description <text>Theme description
--visibility <private|public>Theme visibility (default private)
--forkableAllow other users to fork this theme
--price-cents <int>Price in cents, 0 for free (default 0)
--api-url <url>Override the DevOur server URL
--api-key <key>API key (defaults to the DEVOUR_API_KEY variable)

Configuration Files

The CLI supports JSON and YAML configuration files. By default, it searches for:

  1. devour.json
  2. devour.yml
  3. devour.yaml

Besides the settings below, a synced file holds usageLimits, collections, forms, products, pages, and navSections, and locales live in a locales/ folder next to it. See Collections & Data Modeling, Pages & Navigation, and Locales & Translations.

Usage Limits and Plans

usageLimits names what your plans limit, such as ["Guides", "Pieces"], up to 10. A collection links to one with "usageLimit": "Guides", or "" to unlink it.

products lists the subscription plans your platform sells, each created in your own Stripe account: { "name", "description", "features", "active", "limits", "amount", "currency", "interval" }. limits sets the plan's number for each usage limit by name, such as { "Guides": 5 }. amount is in the currency's smallest unit, and interval is day, week, month, or year.

The generated platform enforces the limits: a customer creates records in a linked collection until their plan's number, and without a plan can only read. See Usage Limits and What They Cap. A usage limit missing from the file is removed after setup asks, or right away with --yes.

Collection Record Access

Each collection has a recordAccess of private or shared. With private, each signed-in customer of the generated platform sees and edits only the records they created, and admins see every record. With shared, every signed-in customer sees and edits every record. A collection created without recordAccess is private. Leaving it out for an existing collection keeps its current value.

{ "name": "Pieces", "recordAccess": "private", "properties": [] }

Property and Field Types

Collection properties and form fields take one of these type values:

text-input, text-area, number, toggle, checkbox, single-select, multi-select, date, email, phone, address, address-country, color, image, file

single-select and multi-select also need a linkedCollectionId. Use image for a photo and file for any other upload, such as audio.

Page Blocks

A page holds sections, each with its own blocks, and can also hold blocks directly. devour sync writes each section's id, so applying the file updates that section. A section without an id is created. Every block is { "type", "displayOrder", "config" }, and type must be one of the following. The value is case-sensitive.

typeconfig
headingtext, and level: 1, 2 or 3
richTextcontent: HTML
entityListcollectionId, enableCreate, enableEdit, enableDelete
formformId
buttonlabel and linkType: internal with linkPageId, or external with linkUrl

collectionId, formId and linkPageId are the id of that collection, form or page, as devour sync writes it.

{
  "type": "entityList",
  "displayOrder": 0,
  "config": {
    "collectionId": "bafc6c63-a4ed-44af-b1f4-b78e15fb773b",
    "enableCreate": true,
    "enableEdit": true,
    "enableDelete": false
  }
}

collectionId, formId, and label are required, and so is linkType with its matching linkPageId or linkUrl. The others are optional. A left-out enableCreate, enableEdit, or enableDelete is off, and a heading without a level renders at level 3. The builder app starts new blocks with enableCreate and enableEdit on and level at 2.

What the two data blocks do in the generated platform:

Applying a file fails, and the error says why, when it has an unknown block, property, or field type, or when a block's config has a key its type doesn't take, is missing a required key, has a value of the wrong kind, or points at a collection, form, or page that isn't in the project.

JSON Example

{
  "id": "your-project-id",
  "name": "My Project",
  "description": "Customer portal for my store",
  "theme": "default-theme@latest",
  "logoUrl": "assets/logo.png",
  "stripePublicKey": "pk_test_...",
  "stripeSecretKey": "sk_test_...",
  "firebaseApiKey": "AIzaSy...",
  "firebaseAuthDomain": "project.firebaseapp.com",
  "firebaseProjectId": "project-id",
  "firebaseServiceAccount": "secrets/service-account.json",
  "passwordlessSignIn": true,
  "colorMain": "#3B82F6",
  "colorSecondary": "#10B981"
}

YAML Example

id: your-project-id
name: My Project
description: Customer portal for my store
theme: default-theme@latest
logoUrl: assets/logo.png
stripePublicKey: pk_test_...
stripeSecretKey: sk_test_...
firebaseApiKey: AIzaSy...
firebaseAuthDomain: project.firebaseapp.com
firebaseProjectId: project-id
firebaseServiceAccount: secrets/service-account.json
passwordlessSignIn: true
colorMain: '#3B82F6'
colorSecondary: '#10B981'

Available Settings

KeyDescriptionValue
nameProject nametext
descriptionProject descriptiontext
themeTheme of the generated platformname@version, such as default-theme@latest
logoUrlLogopath or URL of an SVG, PNG, JPG, GIF, or WebP up to 5 MB
stripeSecretKeyStripe secret keytext
stripePublicKeyStripe public keytext
firebaseApiKeyFirebase API keytext
firebaseAuthDomainFirebase auth domaintext
firebaseProjectIdFirebase project IDtext
firebaseStorageBucketFirebase storage buckettext
firebaseMessagingSenderIdFirebase messaging sender IDtext
firebaseAppIdFirebase app IDtext
firebaseMeasurementIdFirebase measurement IDtext
firebaseServiceAccountFirebase service accountpath to the JSON file
passwordlessSignInPasswordless sign-in in the generated platformtrue or false
resendApiKeyResend API keytext
resendFromEmailAddress emails are sent fromemail address
databaseTypeDatabase typesql or firestore
dbHostDatabase hosttext
dbPortDatabase porttext
dbUserDatabase usertext
dbNameDatabase nametext
dbPasswordDatabase passwordtext
colorMainMain colorhex color, such as #3B82F6
colorSecondarySecondary colorhex color
colorAlertAlert colorhex color
colorErrorError colorhex color
colorSuccessSuccess colorhex color
colorBackgroundBackground colorhex color
colorInkInk (text) colorhex color
colorDisabledDisabled colorhex color
versionCurrent project versionsemantic version, such as 1.0.0
autoIncrementVersionAuto-increment the versiontrue or false
autoDeleteOldVersionsDelete old versions automaticallytrue or false

To upload a logo or a service account with setup, set logoUrl or firebaseServiceAccount to a URL or a file path. A URL or a file outside the project directory is uploaded, copied into assets/ or secrets/ next to the configuration file, and replaced by that path. A file inside the project directory, such as one you put next to the configuration file, is uploaded when it's new or has changed since the last devour sync or devour setup, and skipped otherwise. setup uploads files before it sends the settings that need them. logoUrl and autoDeleteOldVersions can only be set from a configuration file, not with --key.

Colors must be 6-digit hex values such as #3B82F6. The bundle replaces any other format with the default color.

The database settings only reach the bundle once Use default Dockerized database is turned off in the web app. That switch can't be changed from the CLI. See Database Setup.

Help

devour --help
devour <command> --help
devour config
devour --version

Each command's help ends with an example and a link to its section here. devour config prints everything a configuration file can hold: every setting with its value format, the shape of collections, forms, pages, and navigation, and the property, field, and block types. devour --version prints the CLI's own version.

Exit Codes

CodeDescription
0Success
1No valid API key was saved, theme upload failed, or theme validate found a problem

Other commands print their errors and exit with code 0, so check their output when an agent or a script runs them.

Related Documentation