@walkeros/cli
Command-line tools for building, testing, and running walkerOS event collection
flows.
What is this?
The walkerOS CLI is a developer tool that:
- Bundles flow configurations into optimized JavaScript
- Simulates event processing for testing (via
push --simulate)
- Runs flows locally without Docker daemon
Think of it as your development toolchain for walkerOS - from config to running
production bundles.
When to Use the CLI
The CLI is for Bundled mode — when you want config-as-code and separate
deployment:
| Static sites, landing pages | React/Next.js apps |
| Docker/server deployments | TypeScript projects |
| CI/CD versioned configs | Programmatic control |
| Marketing/GTM workflows | Build-time type safety |
For Integrated mode (importing directly into your app), see the
Collector package.
Installation
npm install -g @walkeros/cli
npm install @walkeros/cli
Quick Start
walkeros bundle flow.json
walkeros push flow.json --event '{"name":"product view"}' --simulate destination.demo
walkeros push flow.json --event '{"name":"product view"}'
walkeros run dist/flow.mjs --port 3000
Commands
bundle
Generate optimized JavaScript bundles from flow configurations.
walkeros bundle <config-file> [options]
Config files can be local paths or HTTP(S) URLs:
walkeros bundle ./config.json
walkeros bundle https://example.com/config.json
Options:
--flow <name> - Flow name for multi-flow configs
--all - Build all flows for multi-flow configs
--stats - Show bundle statistics
--json - Output as JSON (implies --stats)
--no-cache - Disable package caching
-v, --verbose - Verbose output
-s, --silent - Suppress output
Examples:
walkeros bundle examples/server-collect.json --stats
walkeros bundle flow.json -o ./build/
Server bundles use nft tracing
Server flows (platform: "server") are bundled with @vercel/nft. The CLI
externalizes every step package, traces the entry to discover which files are
actually reachable at runtime, and copies only those files into
dist/node_modules/. Step packages are installed via pacote, driven by the
config.bundle.packages field in flow.json. You do not need to run
npm install for step packages: only @walkeros/cli belongs in your
package.json devDependencies.
The output is always a directory:
dist/
├── flow.mjs # ESM entry point
├── package.json # informational sidecar
└── node_modules/ # only the files nft traced
For web flows the output stays a single self-contained file (default
dist/walker.js).
push
Execute your flow with real API calls, or simulate specific steps with
--simulate. Accepts either a config JSON (which gets bundled) or a pre-built
bundle.
walkeros push <input> --event '<json>' [options]
Input types:
- Config JSON - Bundled and executed
- Pre-built bundle (
.js/.mjs) - Executed directly
The CLI auto-detects the input type by attempting to parse as JSON.
Options:
-e, --event <source> - Event to push (JSON string, file path, or URL)
Required (unless simulating a source)
--flow <name> - Flow name (for multi-flow configs)
-p, --platform <platform> - Platform override (web or server)
--simulate <step> - Simulate a step (repeatable). Mocks the step's push,
captures result. Use destination.NAME or source.NAME.
--mock <step=value> - Mock a step with a specific return value (repeatable).
Use destination.NAME=VALUE.
--snapshot <source> - JS file to eval before execution. Sets global state
(window.dataLayer, process.env, etc.).
--json - Output results as JSON
-v, --verbose - Verbose output
-s, --silent - Suppress output (for CI/CD)
Event input formats:
walkeros push flow.json --event '{"name":"page view","data":{"title":"Home"}}'
walkeros push flow.json --event ./events/order.json
walkeros push flow.json --event https://example.com/sample-event.json
Simulation examples:
walkeros push flow.json -e event.json --simulate destination.ga4
walkeros push flow.json --simulate source.browser
walkeros push flow.json -e event.json --mock destination.ga4='{"status":"ok"}'
Bundle input:
walkeros push dist/flow.mjs --event '{"name":"order complete"}'
walkeros push dist/walker.js --platform web --event '{"name":"order complete"}'
Push modes:
| Real | (none) | Real HTTP requests | Integration testing |
| Simulate | --simulate | Mocked (captured) | Safe local testing |
| Mock | --mock | Returns mock value | Controlled testing |
Use --simulate first to validate safely, then push without flags for real
integrations.
setup
Run the optional setup() lifecycle on a single component to provision external
resources (BigQuery datasets, Pub/Sub topics, SQLite tables, webhook
registrations).
walkeros setup <target> [options]
Target format: <kind>.<name> matching walkeros push --simulate. Valid
kinds: source, destination, store. Transformers are pure functions and
have no setup.
Options:
-c, --config <path> - Flow config file (default: ./flow.json)
-f, --flow <name> - Flow name for multi-flow configs
--json - Output as JSON
-v, --verbose - Verbose output
-s, --silent - Suppress output
Behavior:
- Loads the flow config, resolves the named component, imports its package, and
calls
setup({ id, config, env, logger }). No collector boot, no event
pipeline, no destinations are pushed to.
- Skips with an explanatory message in three cases: the package has no
setup
function, config.setup === false, or config.setup is unset.
- When
setup() returns a non-undefined value, the CLI emits it as JSON on
stdout for jq-style scripting.
- Exit code
0 on success or skip, non-zero on failure.
Operator-time, never automatic. Setup is explicit only. It is never
triggered by push, simulate, deploy, or the long-running runtime.
Operators run it once when provisioning, and again only when external resources
need to be re-provisioned.
IAM note: Setup typically needs higher permissions than runtime push (for
example, "create dataset" vs "write rows"). Operators commonly run setup with a
separate service account or different credentials than the runtime uses.
Examples:
walkeros setup destination.bigquery
walkeros setup destination.bigquery --flow analytics
walkeros setup destination.bigquery --config ./flows/prod.json
walkeros setup destination.bigquery --json | jq .datasetCreated
walkeros setup source.events-in
run
Run flows locally (no Docker daemon required).
walkeros run <config-file> [options]
Options:
-p, --port <number> - Server port
-h, --host <host> - Server host
--json - Output as JSON
-v, --verbose - Verbose output
-s, --silent - Suppress output
Examples:
walkeros run examples/server-collect.json --port 3000
walkeros run dist/flow.mjs --port 3000
How it works:
- JSON configs are auto-bundled to temp
.mjs
.mjs bundles are used directly
- Runs in current Node.js process
- Press Ctrl+C for graceful shutdown
validate
Validate flow configurations, events, mappings, or contracts.
walkeros validate <config-file> [options]
By default, validates a Flow.Config file — checking schema, references, and
cross-step example compatibility.
Options:
--type <type> - Validation type (default: flow). Also accepts: event,
mapping, contract
--path <path> - Validate a specific entry against its package schema (e.g.,
destinations.snowplow, sources.browser)
--flow <name> - Flow name for multi-flow configs
--strict - Treat warnings as errors
--json - Output as JSON
-v, --verbose - Verbose output
-s, --silent - Suppress output
Exit codes: 0 = valid, 1 = errors, 2 = warnings (with --strict), 3 =
input error
Examples:
walkeros validate flow.json
walkeros validate flow.json --flow analytics
walkeros validate event.json --type event
walkeros validate flow.json --json --strict || exit 1
walkeros validate flow.json --path destinations.snowplow
deploy
Deploy flows to walkerOS cloud.
walkeros deploy start <flowId> [options]
walkeros deploy status <flowId> [options]
Options:
--project <id> - Project ID (defaults to WALKEROS_PROJECT_ID)
--flow <name> - Flow name for multi-config flows
--no-wait - Do not wait for deployment to complete (start only)
--json - Output as JSON
-v, --verbose - Verbose output
-s, --silent - Suppress output
Examples:
walkeros deploy start cfg_abc123
walkeros deploy start cfg_abc123 --flow web
walkeros deploy status cfg_abc123 --flow server
When a flow has multiple configs, the CLI requires --flow <name> to specify
which one to deploy. If omitted, the error message lists available names.
Caching
The CLI implements intelligent caching for faster builds:
Package Cache
- NPM packages are cached in
.tmp/cache/packages/
- Mutable versions (
latest, ^, ~) are re-checked daily
- Exact versions (
0.4.1) are cached indefinitely
Build Cache
- Compiled bundles are cached in
.tmp/cache/builds/
- Cache key based on flow.json content + current date
- Identical configs reuse cached build within the same day
Cache Management
walkeros cache info
walkeros cache clear
walkeros cache clear --packages
walkeros cache clear --builds
walkeros bundle flow.json --no-cache
Flow Configuration
Flow configs use the Flow.Json format with version and flows:
{
"version": 4,
"flows": {
"default": {
"config": {
"platform": "server",
"bundle": {
"packages": {
"@walkeros/collector": { "imports": ["startFlow"] },
"@walkeros/server-source-express": {},
"@walkeros/destination-demo": {}
}
}
},
"sources": {
"http": {
"package": "@walkeros/server-source-express",
"config": {
"settings": { "path": "/collect", "port": 8080 }
}
}
},
"destinations": {
"demo": {
"package": "@walkeros/destination-demo",
"config": {
"settings": { "name": "Demo" }
}
}
},
"collector": { "run": true }
}
}
}
Platform is set via config.platform ("web" or "server"). The
config.bundle.packages field declares what pacote should install.
config.bundle.overrides pins transitive dependency versions when needed.
Package Configuration Patterns
The CLI automatically resolves imports based on how you configure packages:
1. Default exports (recommended for single-export packages):
{
"packages": {
"@walkeros/server-destination-api": {}
},
"destinations": {
"api": {
"package": "@walkeros/server-destination-api"
}
}
}
The CLI generates:
import _walkerosServerDestinationApi from '@walkeros/server-destination-api';
2. Named exports (for multi-export packages):
{
"packages": {
"@walkeros/server-destination-gcp": {}
},
"destinations": {
"bigquery": {
"package": "@walkeros/server-destination-gcp",
"code": "destinationBigQuery"
},
"analytics": {
"package": "@walkeros/server-destination-gcp",
"code": "destinationAnalytics"
}
}
}
The CLI generates:
import { destinationBigQuery, destinationAnalytics } from '@walkeros/server-destination-gcp';
3. Utility imports (for helper functions):
{
"packages": {
"lodash": { "imports": ["get", "set"] }
},
"mappings": {
"custom": {
"data": "({ data }) => get(data, 'user.email')"
}
}
}
The CLI generates: import { get, set } from 'lodash';
Key points:
- Omit
packages.imports for destinations/sources - the default export is used
automatically
- Only specify
code when using a specific named export from a multi-export
package
- Use
packages.imports only for utilities needed in mappings or custom code
Local Packages
Use local packages instead of npm for development or testing unpublished
packages:
{
"packages": {
"@walkeros/collector": {
"path": "../packages/collector",
"imports": ["startFlow"]
},
"@my/custom-destination": {
"path": "./my-destination",
"imports": ["myDestination"]
}
}
}
Resolution rules:
path takes precedence over version
- Relative paths are resolved from the config file's directory
- If
dist/ folder exists, it's used; otherwise package root is used
Dependency resolution:
When a local package has dependencies on other packages that are also specified
with local paths, the CLI will use the local versions for those dependencies
too. This prevents npm versions from overwriting your local packages.
{
"packages": {
"@walkeros/core": {
"path": "../packages/core",
"imports": []
},
"@walkeros/collector": {
"path": "../packages/collector",
"imports": ["startFlow"]
}
}
}
In this example, even though @walkeros/collector depends on @walkeros/core,
the local version of core will be used (not downloaded from npm).
See examples/ for complete working configurations.
Programmatic API
Use commands programmatically:
import { bundle, push, runCommand } from '@walkeros/cli';
await bundle({
config: './flow.json',
stats: true,
});
const result = await push(
'./flow.json',
{ name: 'page view', data: { title: 'Test' } },
{ simulate: ['destination.ga4'], json: true },
);
await push('./flow.json', { name: 'page view', data: { title: 'Test' } });
await runCommand({
config: './flow.json',
port: 3000,
verbose: true,
});
Examples
Working example configs in examples/:
- server-collect.json - Basic server-side collection
- server-collection.json - Advanced server setup
- web-serve.json - Web demo with API destination
- web-tracking.json - General web tracking
Try them:
walkeros bundle examples/server-collect.json --stats
walkeros push \
examples/web-serve.json \
--event '{"name":"product view","data":{"id":"P123"}}' \
--simulate destination.demo
walkeros run examples/server-collect.json --port 3000
Development Workflow
Typical development cycle:
vim my-flow.json
walkeros push \
my-flow.json \
--event '{"name":"product view"}' \
--simulate destination.demo \
--verbose
walkeros bundle my-flow.json --stats
walkeros run dist/flow.mjs --port 3000
curl -X POST http://localhost:3000/collect \
-H "Content-Type: application/json" \
-d '{"name":"page view","data":{"title":"Home"}}'
Architecture
CLI
├─ Pacote installs flow.json packages (no user-side npm install)
├─ esbuild externalizes step packages, emits ESM entry
├─ @vercel/nft traces entry, copies only used files
└─ Output: dist/{flow.mjs, package.json, node_modules/} (server)
dist/walker.js (web)
Key principle: CLI handles both build-time install/trace/bundle and runtime
execution.
Runner (Docker)
The walkeros/flow Docker image is a self-bundling runner for production
deployment. It supports four deployment modes — from fully local to fully
managed — all using the same image and config format.
docker run -v ./flow.json:/app/flow.json -e BUNDLE=/app/flow.json walkeros/flow
docker run -v ./flow.json:/app/flow.json \
-e BUNDLE=/app/flow.json \
-e WALKEROS_TOKEN=sk-walkeros-xxx \
-e PROJECT_ID=proj_xxx \
walkeros/flow
docker run \
-e WALKEROS_TOKEN=sk-walkeros-xxx \
-e PROJECT_ID=proj_xxx \
-e FLOW_ID=flow_xxx \
walkeros/flow
Each step adds one env var. Same runner, same config, same bundle pipeline.
See the Runner documentation for
the full reference (env vars, pipeline, caching, hot-swap, health checks,
troubleshooting).
Using Node.js
Run the bundle directly with the CLI:
walkeros bundle flow.json
walkeros run dist/flow.mjs --port 8080
This runs the flow in the current Node.js process, suitable for deployment on
platforms like AWS Lambda, Google Cloud Run, or any Node.js hosting.
Requirements
- Node.js: 18+ or 22+
- Docker: Not required for CLI (only for production deployment)
Type Definitions
See src/types.ts for TypeScript interfaces.
Related
License
MIT © elbwalker