Skip to main content

CLI Generation Commands

The CLI provides four commands that cover the full content lifecycle: generating work content, regenerating markdown, syncing the website repository, and deploying to production. Each command is a subcommand of work.

Source: apps/cli/src/commands/work/

Command Overview

CommandDescriptionSource File
work generateGenerate items and create/update the data repositorygenerate.ts
work regenerate-markdownRegenerate the README.md from existing dataregenerate-markdown.ts
work update-websiteSync data repository content to the website repositoryupdate-website.ts
work deployDeploy the website to the configured providerdeploy.ts

Generate Content

ever-works work generate

The most complex CLI command. It guides the user through a multi-step configuration wizard, validates provider setup, and starts the generation pipeline.

Prerequisites

  • User must be authenticated.
  • User must have editor role or higher on the selected work.
  • A git provider (GitHub) must be connected.
  • No generation may already be in progress.

Interactive Flow

Step 1: Work Selection

Prompts the user to select from their works. Checks that generation is not already running:

if (work.generateStatus?.status === GenerateStatusType.GENERATING) {
// Already in progress — show current step and exit
}

Step 2: Git Provider Check

Iterates over all enabled git providers and tests their connection. If none is connected, directs the user to the web dashboard to authenticate.

Step 3: Pipeline Selection

Loads the generator form schema and prompts the user to select a generation pipeline. The schema defines available pipelines and their provider requirements.

When a pipeline is selected, the schema is re-fetched with the pipeline ID to get filtered provider categories specific to that pipeline.

Step 4: Provider Selection

For each provider category in the schema (e.g. ai-provider, search, screenshot), the user selects which plugin to use:

const individualProviders = await generatePrompt.promptIndividualProviders(schema, lastRequestData?.providers);

Previous selections from the last generation run are used as defaults.

Step 5: Required Fields

Two fields are always collected:

FieldDescription
nameThe work name (read-only, pre-filled)
promptThe generation prompt (pre-filled from last generation if available)

Step 6: Dynamic Plugin Fields

If the selected pipeline defines pluginFields, the CLI prompts for each one. Default values come from the schema's defaultValues merged with the last run's pluginConfig (only when the pipeline matches).

Plugin fields are organized into pluginGroups for logical grouping in the prompt interface.

Step 7: Provider Validation

Before proceeding, the CLI validates that all selected providers are properly configured:

const unconfigured = findUnconfiguredProviders(providerSelections, schema);
if (unconfigured.length > 0) {
console.log(`Unconfigured providers: ${unconfigured.join(', ')}`);
// Exit — user must configure in Settings > Plugins
}

Step 8: Generation Options

For previously generated works, the user chooses:

OptionValuesDescription
generation_methodCREATE_UPDATE, RECREATEWhether to update existing items or start from scratch
update_with_pull_requesttrue, falseWhether updates go through a PR workflow
website_repository_creation_methodCREATE_USING_TEMPLATE, etc.How the website repository is created

Selecting RECREATE triggers an extra confirmation since it deletes existing items.

New works always use CREATE_UPDATE without prompting.

Step 9: Confirm and Start

The CLI displays a summary of all selections and asks for final confirmation. On confirmation, it calls apiService.generateContent() and directs the user to check progress with work status.

Plugin Config Sanitization

Before sending to the API, plugin config values are sanitized:

  • null and undefined values are removed.
  • String arrays are trimmed and cleaned of control characters.
  • URL arrays are trimmed but not character-cleaned.

Regenerate Markdown

ever-works work regenerate-markdown

Regenerates the README.md file in the data repository without re-running the full generation pipeline. Useful for updating presentation while preserving existing data.

Flow

  1. Authenticate and select work.
  2. Check edit permissions.
  3. Confirm the operation.
  4. Call apiService.regenerateMarkdown(workId).
  5. Show status and next steps.

What It Does

  • Regenerates the README.md file for the work's data repository.
  • Preserves all existing item data.
  • Updates only the presentation layer (markdown formatting).

Next Steps After Success

The CLI suggests:

- Check your data repository for the updated README.md
- Review the changes and commit if satisfied
- Use "work update-website" to update the website

Update Website

ever-works work update-website

Syncs content from the data repository to the website repository. This prepares the website for deployment without triggering a deploy.

Flow

  1. Authenticate and select work.
  2. Check edit permissions.
  3. Display the target repository ({owner}/{slug}-website).
  4. Confirm the operation.
  5. Call apiService.updateWebsite(workId).
  6. Show status, repository URL, and next steps.

What It Does

  • Copies generated content from the data repository to the website repository.
  • Updates the website source files to reflect the latest data.
  • Does not trigger a deployment.

Next Steps After Success

- Check the website repository for updates
- Use "work deploy" to deploy the website
- Review the changes before deployment

Deploy Website

ever-works work deploy

Deploys the website to the configured deployment provider (e.g. Vercel). Handles provider selection, team scoping, and deployment status polling.

Prerequisites

  • Work content must be generated (generateStatus === GENERATED).
  • A deployment provider must be configured or selected during the command.
  • The deployment provider's API token must be configured.

State Machine

The deploy command implements a state machine with four states:

StateConditionBehavior
ANo deployProvider setPrompt user to select a provider. If valid, proceed to deploy.
BHas provider, canDeploy=false, shared workTell user the owner must configure their token.
CHas provider, canDeploy=false, owned workTell user to configure their token. Offer to switch providers.
DHas provider, canDeploy=trueExecute the deployment.

Deployment Execution

The executeDeploy() function handles the full deployment lifecycle:

  1. Lookup existing deployment -- Checks if the work already has a live deployment and shows its URL.
  2. Team selection -- If the user's deployment account has teams, prompts for which team to deploy under.
  3. Confirmation -- Shows the source repository and what will happen.
  4. Deploy -- Calls apiService.deployWebsite(workId, { teamScope }).
  5. Poll for status -- Polls the work's deploymentState every 5 seconds.

Deployment Status Polling

const STOP_STATES = ['READY', 'ERROR', 'CANCELED', 'TIMEOUT'];

while (true) {
const { work } = await apiService.getWork(workId);

if (STOP_STATES.includes(work.deploymentState)) {
// Show final status and website URL
break;
}

// Update spinner text with current state
await new Promise((resolve) => setTimeout(resolve, 5000));
}

The isDeploying() helper prevents false positives by checking that the deployment was started within the last 10 minutes:

function isDeploying(work: Work) {
const hasDeploymentState = ['INITIALIZING', 'QUEUED', 'BUILDING'].includes(work.deploymentState);
const hasStartedAt =
work.deploymentStartedAt && new Date(work.deploymentStartedAt) > new Date(Date.now() - 10 * 60 * 1000);
return Boolean(hasDeploymentState && hasStartedAt);
}

Terminal States

StateSpinnerOutput
READYSuccessWebsite URL
ERRORFailError message if available
CANCELEDWarning--
TIMEOUTFail--

Common Patterns

All four commands share these patterns:

Authentication Gate

await requireAuth();

Every command requires an active session.

Work Selection

const selection = await workPrompt.promptWorkSelection();
if (selection.cancelled || !selection.work) return;

Interactive work picker with role and sharing information.

Permission Check

if (!canEdit(role)) {
// Show error — requires editor or higher
return;
}

Error Handling

All commands wrap their logic in try/catch and use handleCliError() for consistent error formatting, followed by process.exit(1).

Full Lifecycle Example

A typical workflow using all four commands:

# 1. Generate work content
ever-works work generate
# Select work, configure providers, set prompt, confirm

# 2. (Optional) Regenerate markdown if data format changes
ever-works work regenerate-markdown

# 3. Sync to website repository
ever-works work update-website

# 4. Deploy to production
ever-works work deploy
# Select team (if applicable), confirm, wait for READY