CLI Usage
Synode includes a CLI for generating synthetic data from config files. Install it globally or use it as a project dependency.
Install
# Global install
npm install -g @synode/cli
# Or as a project dependency (included when you run synode init)
npm install @synode/cliQuick Start
# Scaffold a new project interactively
synode init
# Generate data
synode generate synode.config.ts
# Validate config without generating
synode validate synode.config.ts
# Reverse-engineer a config from event data
synode analyze
# Show help
synode --help
synode generate --helpCommands
synode init [dir]
Interactive project scaffolder. Creates a complete Synode project with config, dependencies, and optional example journeys.
synode init # Prompts for project name
synode init my-project # Creates my-project/ directoryThe scaffolder prompts for:
- Project name — directory to create
- Adapters — which output adapters to install (File, HTTP, BigQuery, Stream, Composite)
- Example journey — include a working browse-and-purchase example
- CLAUDE.md sections — AI assistant context (API reference, error codes, architecture)
- Package manager — pnpm, npm, or yarn
After scaffolding, it installs dependencies and shows next steps using your chosen package manager.
synode generate <config>
Loads the config file and runs event generation. Shows progress with timing and events/sec.
synode generate synode.config.ts
synode generate synode.config.ts --users 5000 --lanes 4
synode generate synode.config.ts --output events.jsonl
synode generate synode.config.ts --output ./out/ --format csvWhen --output is a directory (or a path without an extension), the CLI automatically creates a file named events.{ext} inside it.
TypeScript config files are loaded automatically using tsx — no compilation step needed.
synode validate <config>
Validates the config file structure without generating any events. Shows a pass/fail summary for each journey. Exits with code 0 on success, 1 on failure.
synode validate synode.config.tsOutput:
Validating 3 journeys...
✓ browse-session
✓ purchase-flow
✗ checkout — bounceChance must be between 0 and 1
2 passed, 1 failedsynode analyze
Reverse-engineers a Synode config from real event data. Place your CSV, JSONL, or JSON files in an input/ directory and run the wizard. See the Analyzer guide for details.
synode analyze # Full wizard: parse → detect → mine → compile
synode analyze --compile-only # Re-compile from existing input/analysis.jsonThe analyzer:
- Parses event data and auto-detects the schema (GA4, Segment, Mixpanel, or custom)
- Discovers actions, sequences, adventures, and journeys from behavioral patterns
- Generates complete TypeScript config files ready for
synode generate - Optionally enhances names and conditions using AI (Anthropic or Google)
- Detects and offers to clean up stale files from previous runs
synode update
Checks for and installs updates to Synode packages.
synode updateFlags
All flags apply to the generate command. They override config file values.
| Flag | Short | Type | Description |
|---|---|---|---|
--users <n> | -u | number | Override user count |
--lanes <n> | -l | number | Override lane count |
--tick <dur> | string | Override tick interval (e.g., 1m) | |
--scatter <n> | number | Override scatter factor (0-1) | |
--duration <dur> | string | Simulation duration (e.g., 7d) | |
--start <date> | string | Simulation start date (ISO string) | |
--end <date> | string | Simulation end date (ISO string) | |
--stream | boolean | Enable real-time streaming mode | |
--output <path> | -o | string | Output file or directory path |
--format <fmt> | -f | string | Output format: json, jsonl, csv |
--dry-run | boolean | Validate config, generate 1 user only | |
--quiet | -q | boolean | Suppress progress output |
--version | -V | Show version number | |
--help | -h | Show help for any command |
Config File Format
The config file exports a set of named fields that the CLI reads. Run synode init to scaffold one, or use synode analyze to generate one from event data.
import { definePersona, weighted, generate } from '@synode/core';
import type { Journey, TimeConfig, SimulationConfig, DatasetDefinition } from '@synode/core';
import { browseJourney } from './src/journeys/Browse.js';
import { products } from './src/datasets/Products.js';
// Named exports — used by `synode generate`
export const journeys: Journey[] = [browseJourney];
export const time: TimeConfig = { duration: '7d' };
export const simulation: SimulationConfig = { users: 1000, lanes: 4, tick: '1m', scatter: 0.1 };
export const datasets: DatasetDefinition[] = [products];
export const persona = definePersona({
id: 'shopper',
name: 'Shopper',
attributes: {
locale: weighted({ en: 0.5, de: 0.3, fr: 0.2 }),
},
});
// Direct execution — also works with `npx tsx synode.config.ts`
await generate(journeys, { time, simulation, datasets, persona });Required Exports
| Export | Type | Required | Description |
|---|---|---|---|
journeys | Journey[] | Yes | Journey definitions to execute |
time | TimeConfig | Yes | Time window for the simulation |
simulation | SimulationConfig | Yes | Users, lanes, tick, scatter |
datasets | DatasetDefinition[] | No | Datasets to hydrate before execution |
persona | PersonaDefinition | No | Persona for user attribute generation |
TimeConfig
// Duration-based (most common)
export const time = { duration: '30d' };
// Fixed window
export const time = { start: new Date('2026-01-01'), end: new Date('2026-02-01') };
// Start + duration
export const time = { start: new Date('2026-01-01'), duration: '14d' };SimulationConfig
export const simulation = {
users: 1000, // 1 to 10,000,000
lanes: 4, // 1 to 10,000 — concurrent execution slots
tick: '1m', // Clock interval per tick
scatter: 0.1, // 0-1 — jitter applied to waits and cooloffs
};AdapterConfig
The CLI supports two adapter types via config file:
// Console output (default — writes to stdout)
adapter: { type: 'console' }
// File output
adapter: { type: 'file', path: './output/events.jsonl', format: 'jsonl' }When --output is passed as a flag, it creates a file adapter. Format is inferred from the file extension or from the --format flag.
Example Workflow
# 1. Scaffold a new project
synode init my-cdp-data
# 2. Enter the project
cd my-cdp-data
# 3. Edit synode.config.ts with your journeys, persona, datasets
# 4. Dry run to validate
synode generate synode.config.ts --dry-run
# 5. Generate a small sample
synode generate synode.config.ts --users 100 --output ./output/
# 6. Full generation
synode generate synode.config.ts --users 50000 --lanes 8 --output ./output/events.jsonlOr reverse-engineer from existing data:
# 1. Place event files in input/
mkdir input && cp events.csv input/
# 2. Run the analyzer
synode analyze
# 3. Review and run the generated config
synode generate synode.config.tsError Handling
Errors include the CLI version and a pre-filled GitHub issue link:
Error: Config file not found: /path/to/missing.ts
synode v5.0.14 on v24.12.0
Report: https://github.com/digitl-cloud/synode/issues?title=...Set DEBUG=1 to include the full stack trace in error output.
