From walkeros
Bundles, tests, and deploys walkerOS tracking flows. Use for local event servers, simulated pushes, config validation, and flow.json setup.
How this skill is triggered — by the user, by Claude, or both
Slash command
/walkeros:walkeros-using-cliThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
The walkerOS CLI (`walkeros`) bundles, tests, and runs event collection flows.
The walkerOS CLI (walkeros) bundles, tests, and runs event collection flows.
Core workflow:
# Install
npm install -g @walkeros/cli
# Bundle a flow
walkeros bundle flow.json
# Test with simulated event
walkeros push flow.json -e '{"entity":"page","action":"view"}' --simulate destination.demo
# Push real event
walkeros push flow.json -e '{"entity":"page","action":"view"}'
| Command | Purpose | Safe? |
|---|---|---|
bundle | Generate JS bundle from config | ✅ |
push | Execute with real API calls (or --simulate for mocked) | ⚠️ |
run | Local HTTP event collection | ✅ |
deploy | Deploy flows to cloud | ⚠️ |
previews | Manage preview bundles for testing on live sites | ⚠️ |
validate | Validate configs/events | ✅ |
cache | Manage caching | ✅ |
For detailed command reference, see commands-reference.md.
1. Write flow.json config
2. Bundle: walkeros bundle flow.json
3. Simulate: walkeros push flow.json -e event.json --simulate destination.demo
4. Fix issues, repeat 2-3
5. Push test: walkeros push flow.json -e event.json
6. Deploy: walkeros deploy start <flowId>
# Bundle specific flow
walkeros bundle flow.json --flow myFlow
# Bundle all flows
walkeros bundle flow.json --all
# Test specific flow
walkeros push flow.json --flow myFlow -e event.json --simulate destination.demo
# HTTP event collection server
walkeros run flow.json --port 3000
Server port note: The --port flag (or PORT env var) is forwarded at
runtime to all source configs that have a port setting. You don't need to
hardcode ports in the flow config — set port: 8080 as a default and let the
runtime override it.
{
"version": 4,
"flows": {
"default": {
"config": {
"platform": "web",
"bundle": {
"packages": {
"@walkeros/web-destination-gtag": {}
}
}
},
"destinations": {
"gtag": {
"package": "@walkeros/web-destination-gtag",
"config": { "measurementId": "G-XXXXXX" }
}
}
}
}
}
{
"version": 4,
"flows": {
"<flowName>": {
"config": {
"platform": "web" | "server", // Platform (required)
"settings": {}, // Platform-specific settings (optional)
"bundle": {
"packages": {}, // NPM packages pacote will install
"overrides": {}, // Transitive dep version pins (npm-style)
"traceInclude": [] // Optional: nft escape hatch (paths/globs)
}
},
"sources": {}, // Event sources
"destinations": {}, // Event destinations
"transformers": {}, // Transformer chain (optional)
"mappings": {}, // Event transformation rules
"collector": {} // Collector configuration
}
}
}
You do NOT need npm install for step packages. flow.json's
config.bundle.packages is the single source of truth. Pacote installs them
transparently when you run walkeros bundle. Only @walkeros/cli belongs in
your project's package.json (as a devDependency).
config.bundle.overrides pins transitive dependency versions. Use it when a
vendor SDK's declared peer/dep range conflicts with another required version in
the same tree. Example: {"@amplitude/analytics-types": "2.11.1"} forces that
exact version everywhere in the install graph. Direct packages specs always
win over overrides; overrides only substitute transitive resolution.
Schema version stays at 4. Build-time fields live under
flow.<name>.config.bundle.{packages, overrides, traceInclude}. The
flow.<name>.config.bundle.external sub-field is no longer supported in
@walkeros/cli@4.x.
For detailed configuration options, see flow-configuration.md.
--stepTarget a specific step and provide input as SourceInput
({ content, trigger? }):
# Simulate a source step with trigger metadata
walkeros push flow.json --simulate source.browser --event '{"content":"<html>...","trigger":{"type":"click"}}'
# Simulate a destination step with an event
walkeros push flow.json --simulate destination.gtag -e '{"entity":"order","action":"complete","data":{"total":149.97}}'
Example output:
Step: destinations.gtag
in: { name: "order complete", data: { id: "ORD-123", total: 149.97 } }
out: ["event", "purchase", { transaction_id: "ORD-123", value: 149.97 }]
Status: PASS
flow_simulate)From an AI assistant the equivalent tool is flow_simulate. A few specifics:
step is required. Pass the target as "type.name", e.g.
"source.browser", "collector.default", "destination.gtag", or
"transformer.router". There is no all-steps mode.source, collector, transformer, destination.
Source-step event shape is { content, trigger? }, where content is the
walkerOS event { name, data } and trigger is optional
{ type?, options? }. There is no env field. Destination and transformer
steps take a plain walkerOS event { name, data, consent? }.collector is the enrichment step. It takes a post-next partial event
plus an optional state snapshot { consent?, user?, globals?, timing? },
applies the collector's createEvent, and returns the fully enriched event.transformer steps accept an optional ingest (a raw ingest without
_meta). Supply it to test a request decoder standalone, for example a GA4
decoder reading ctx.ingest.url: pass ingest: { url: "..." } with the
event.@walkeros/source-demo
demo source.configPath accepts a cloud flow id (flow_... / cfg_...), resolved
the same way flow_load does, so you can simulate a saved flow without a file
round-trip. Repeated simulations of the same configuration reuse a prebuilt
bundle for faster runs; local file paths always rebuild. flow_bundle accepts
a cloud flow id the same way.flow_load loads a flow from a local path, URL, inline JSON, or a cloud
flow/config ID (flow_... / cfg_...). Configs returned by flow_load and
flow_manage are round-trip safe: structural values (package names, platform,
IDs) come back literally, so a returned config can be edited and sent back to
flow_manage({ action: "update" }) unchanged.
When an MCP request fails, the diagnostics tool (read-only, no parameters,
works logged out) reports the MCP and CLI versions, the resolved app URL, app
/api/health reachability, the bundled OpenAPI contract version, and which
source served the last package lookup.
Validate schema, references, and cross-step example compatibility:
walkeros validate flow.json
All checks run automatically — schema validation, reference checking, and cross-step example compatibility. No flags needed for full validation.
For full details on writing and testing with step examples, see using-step-examples.
Embed JavaScript functions in JSON configs:
{
"fn": "$code:(event) => event.data.price * 100",
"condition": "$code:(event) => event.data?.value > 100"
}
Important: The CLI bundler converts $code: strings to actual JavaScript
functions during build. This is essential for mappings in JSON configs.
For mapping patterns, see understanding-mapping.
walkeros bundle <config> [options]
Options:
--flow <name> Bundle specific flow (default: "default")
--all Bundle all flows
--stats Show bundle statistics
--json JSON output
--no-cache Skip build cache
-v, --verbose Verbose output
-s, --silent Silent mode
Output:
dist/walker.js (single self-contained IIFE)dist/{flow.mjs, package.json, node_modules/} (always a directory;
nft-traced)flow.tar.gz / flow.tgz (the server bundle directory packed
into a single gzip file)Use -o ./dist/walker.js for web, -o ./dist/ for a server directory, or
-o ./flow.tar.gz for a server archive. Web single-file bundles do not support
archive output.
walkeros push <config|bundle> [options]
Options:
-e, --event <json|file|url> Event to process (required)
--flow <name> Flow to use
-p, --platform <web|server> Platform override
--simulate <step> Simulate a step (repeatable for destination.*). Format: source.NAME | destination.NAME | transformer.NAME
--mock <step=value> Mock a step with a specific return value (repeatable)
--snapshot <source> JS file to eval before execution (sets global state)
walkeros validate <input> [options]
Options:
--type <type> Validation type (default: flow). Also: event, mapping, contract
--path <path> Validate entry against package schema (e.g. destinations.snowplow)
--flow <name> Flow name for multi-flow configs
--strict Treat warnings as errors
--json JSON output
Exit codes:
0 = Valid
1 = Errors found
2 = Warnings (with --strict)
3 = Input error
# HTTP event collection server
walkeros run <config|bundle|archive> [options]
Options:
-p, --port <number> Port (default: 8080)
-h, --host <string> Host (default: 0.0.0.0)
run accepts a flow config, a pre-built bundle, or a .tar.gz/.tgz flow
archive (URL or local file). For an archive, the CLI fetches or reads the gzip,
extracts the bundle and its sibling node_modules/, and runs the entry. This
lets server flows whose step packages are external resolve those packages at
runtime from the extracted node_modules/.
# Run a packed server bundle from a local archive
walkeros run flow.tar.gz --port 8080
# Run a packed server bundle from a URL
walkeros run https://example.com/flow.tar.gz
include: ["./dist"] when output is dist/). The CLI detects this and
errors.settings resolve relative to the bundle, not the project root.gtag-wrapper cause
syntax errors — use gtagWrapper instead.arrify@^3.0.0 vs arrify@^2.0.0), the bundler
resolves the chosen range to a concrete version and nests non-satisfying specs
under their consumer. If a post-install warning surfaces declared-vs-installed
mismatches, pin the dep in config.bundle.overrides. Set
BUNDLER_STRICT_RANGES=0 to bypass strict range validation when the npm
registry is unreachable.Server flows are bundled with @vercel/nft.
The CLI:
flow.<name>.config.bundle.packages into a per-build install root. Users do
not run npm install for step packages; only @walkeros/cli lives in
their package.json.flow.mjs that imports from those
externalized packages.flow.mjs, finds every file actually reachable at runtime
(including __dirname-loaded .proto files and other assets), and copies
only those files into dist/node_modules/.There is no walkerOS.bundle.external annotation. nft figures it out.
Bundle directory (the server flow's unpacked artifact):
dist/
├── flow.mjs # ESM entry, expects to be at /app/flow/flow.mjs in prod
├── package.json # informational sidecar (not used by the runner)
└── node_modules/ # only the files nft traced
The same directory can be packed into a .tar.gz/.tgz archive (see the Bundle
Command section), and walkeros run accepts either form. Web flows are
unchanged: a single dist/walker.js.
FROM node:22-alpine AS builder
WORKDIR /build
RUN npm init -y && npm install --save-dev @walkeros/cli
COPY flow.json ./
RUN npx walkeros bundle flow.json -o dist/
FROM walkeros/flow:4
WORKDIR /app/flow
COPY --from=builder /build/dist/ ./
ENV PORT=8080
EXPOSE 8080
Notes:
@walkeros/cli. flow.json drives every step
package install; pacote handles it.COPY --from=builder /build/dist/ ./ copies the whole directory (flow.mjs +
package.json + node_modules/) into /app/flow/./app/flow/flow.mjs. No BUNDLE env var
needed.traceIncludeIf nft cannot statically reach a runtime asset (rare: require() of a path
constructed from a runtime variable), declare it explicitly under
flow.<name>.config.bundle.traceInclude. Paths and globs both work; both
resolve against the install root, not the project directory:
"flows": {
"default": {
"config": {
"platform": "server",
"bundle": {
"packages": { "@walkeros/server-destination-gcp": {} },
"traceInclude": [
"node_modules/some-pkg/data/*.json",
"node_modules/another-pkg/lib/runtime-loaded.js"
]
}
}
}
}
The bundler caches pacote downloads under process.env.NPM_CACHE_DIR (default
<tmpDir>/cache/npm). On CI, persist that path with actions/cache:
- uses: actions/cache@v4
with:
path: .walkeros-cache/npm
key: walkeros-${{ hashFiles('**/flow.json') }}
- run: WALKEROS_TMP_DIR=.walkeros-cache npx walkeros bundle flow.json -o dist/
CI smoke check:
cd dist && node -e "import('./flow.mjs').then(()=>console.log('ok'))" plus
du -sh node_modules (typical: 30-50MB for GCP destination, 10k+ files; use
.dockerignore).
walkeros validate flow.json --flowwalkeros cache clearwalkeros validate event.jsonwalkeros push flow.json -e event.json --simulate destination.demo -vIf --simulate destination.NAME errors with "not found in collector", the
destination likely has require: ["consent"] in its config. This delays
initialization until a walker consent event fires — which doesn't happen
during simulation.
Fix: Remove or comment out the require field for simulation testing:
{
"destinations": {
"gtag": {
"package": "@walkeros/web-destination-gtag",
"config": {
"settings": { "measurementId": "G-XXXXXX" }
}
}
}
}
If the destination is found but receives 0 events:
consent: { marketing: true }, the
event must include matching consent. Add to event JSON:
{ "name": "page view", "data": {...}, "consent": { "marketing": true } }Web simulations run in JSDOM. fetch and navigator.sendBeacon are polyfilled
as tracked no-ops -- no real HTTP requests are made. Captured network calls are
included in PushResult.networkCalls when present.
Use absolute or relative paths in flow.<name>.config.bundle.packages:
{
"config": {
"platform": "web",
"bundle": {
"packages": {
"my-destination": {
"path": "./local/my-destination"
}
}
}
}
}
The walkerOS app requires a newer @walkeros/cli version for the endpoint you
just called. Upgrade and retry:
npm install -g @walkeros/cli@latest
See Upgrading for the full version-negotiation rules.
| Location | Purpose |
|---|---|
packages/cli/ | CLI source code |
packages/cli/src/commands/ | Command implementations |
packages/cli/examples/ | Example flow configs |
packages/cli/README.md | Full CLI documentation |
Outbound requests to a configured WALKEROS_APP_URL carry an
X-Walkeros-Client: walkeros-cli/{version} header so the host can attribute
usage. No PII; the header is the only client identifier.
The CLI supports anonymous usage telemetry (installation id, command name, outcome, duration, environment) to help improve the tool. Telemetry is off by default and requires explicit opt-in. No persistent identifier is written before consent.
walkeros telemetry enable.walkeros telemetry disable.walkeros telemetry status.DO_NOT_TRACK=1 or
WALKEROS_TELEMETRY_DISABLED=1.WALKEROS_TELEMETRY_DEBUG=1 to print the payload to stderr
(requires opt-in; no network traffic).packages/cli/src/telemetry/flow.json.Detailed References:
npx claudepluginhub elbwalker/walkerosHelps write, simulate, validate, and test walkerOS step examples using structured in/out pairs. Covers authoring to CI integration and documentation.
Provides expert guidance for Vercel Workflow DevKit when building durable workflows, long-running tasks, API routes, or agents needing pause/resume, retries, step execution, or crash-safe orchestration.
Creates bite-sized, testable implementation plans from specs or requirements, with file structure and task decomposition. Activates before coding multi-step tasks.