Skip to content

CLI Reference

The ironflow CLI is the primary interface for running the server, emitting events, invoking functions, debugging runs, and managing environments.

ironflow [command] [flags]
  • All client commands (apikey, audit, circuit-breaker, debounce, emit, env, event, function, inspect, invoke, mcp, org, outbox, platform, policy, project, projection, role, run, secret, server, sql, stream, subscribe, tenant, topic, version, webhook) connect to the server specified by IRONFLOW_SERVER_URL (default: http://localhost:9123)
  • API key authentication is supported via IRONFLOW_API_KEY when the server has auth enabled
  • The --as-org <org_id> global flag allows platform users to impersonate an organization. Requires platform credentials (via ironflow platform login). Sends the platform JWT and sets the X-Ironflow-Org header on requests.
  • The --verbose / -v global flag enables debug-level diagnostic logging on stderr. By default, CLI commands run at warn level (quiet). The serve command defaults to info level so startup messages remain visible. The LOG_LEVEL env var overrides both the flag and defaults.
  • Logs are written to stderr; user-facing output (tables, JSON) goes to stdout. Piping output (e.g., ironflow function list --json | jq .) is unaffected by verbose logging.
  • Platform commands (ironflow platform *) authenticate using stored platform credentials (JWT token in ~/.config/ironflow/credentials.json) obtained via ironflow platform login. Falls back to IRONFLOW_API_KEY if no platform credentials are found.
  • Server commands (serve, init, config, validate, deploy, provision) run locally. Operator commands (cloud) connect directly to the meta-cluster Postgres via IRONFLOW_DATABASE_URL rather than the Ironflow server API.
  • Exit code 0 indicates success; 1 indicates an error

Manage API keys for authentication. Create, list, delete, and rotate API keys.

Terminal window
ironflow apikey <subcommand> [flags]

Subcommands:

SubcommandDescription
createCreate a new API key
listList all API keys
deleteDelete an API key
rotateRotate an API key

Create a new API key with the given name. Returns the key value which must be saved immediately.

Terminal window
ironflow apikey create <name> [flags]

Arguments:

ArgumentRequiredDescription
nameYesName for the new API key

Flags:

FlagShortTypeDefaultDescription
--envstringEnvironment ID to scope the key to
--rolestring[]Role ID to assign (can be specified multiple times)
--expiresstringExpiration duration (e.g. 720h for 30 days)
--platformboolfalseCreate a platform-scoped key (ifplatform_ prefix)
--server-sstringServer URL override

Examples:

Terminal window
# Create a basic API key
ironflow apikey create my-key
# Create a key with roles
ironflow apikey create my-key --role role_abc123 --role role_def456
# Create a key scoped to an environment with expiration
ironflow apikey create my-key --env env_abc123 --expires 720h
# Create a platform key for cross-tenant operations
ironflow apikey create my-platform-key --platform

List all API keys with their IDs, names, prefixes, roles, and timestamps.

Terminal window
ironflow apikey list [flags]

Flags:

FlagShortTypeDefaultDescription
--jsonboolfalseOutput as JSON
--platformboolfalseList only platform-scoped keys
--server-sstringServer URL override

Output:

ID NAME PREFIX ROLES CREATED LAST USED EXPIRES
ak_abc123 my-key ak_abc role_abc123 2026-01-01T00:00:00Z 2026-03-01T12:00:00Z -

Examples:

Terminal window
# List all API keys
ironflow apikey list
# List platform keys only
ironflow apikey list --platform
# List as JSON
ironflow apikey list --json

Delete an API key by its ID. The key is immediately revoked.

Terminal window
ironflow apikey delete <id> [flags]

Arguments:

ArgumentRequiredDescription
idYesAPI key ID to delete

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override

Examples:

Terminal window
ironflow apikey delete ak_abc123

Rotate an API key by its ID. Creates a new key with the same name, environment, and roles. The old key is immediately revoked.

Terminal window
ironflow apikey rotate <id> [flags]

Arguments:

ArgumentRequiredDescription
idYesAPI key ID to rotate

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override

Examples:

Terminal window
ironflow apikey rotate ak_abc123

View and query history inspection (audit trail) records for workflow runs and auth decisions. Uses the ConnectRPC API.

Terminal window
ironflow audit <subcommand> [flags]

Subcommands:

SubcommandDescription
trailView history inspection (audit trail) for a workflow run
auth-trailView auth decision audit trail (Enterprise)

View the audit trail for a specific workflow run with optional filtering.

Terminal window
ironflow audit trail <run-id> [flags]

Arguments:

ArgumentRequiredDescription
run-idYesWorkflow run ID to query

Flags:

FlagShortTypeDefaultDescription
--typestringFilter by event type (e.g., step.completed)
--fromstringFrom timestamp (RFC3339)
--tostringTo timestamp (RFC3339)
--limitint50Maximum events to return
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Output:

TIMESTAMP EVENT TYPE STEP ID PAYLOAD
10:30:15.123 run.created - {"functionId":"fn_abc"}
10:30:15.456 step.created step_001 {"name":"validate-input"}
10:30:16.789 step.completed step_001 {"name":"validate-input"}
Total: 3 events

Examples:

Terminal window
# View all audit events for a run
ironflow audit trail run_abc123
# Filter by event type
ironflow audit trail run_abc123 --type step.completed
# Filter by time range
ironflow audit trail run_abc123 --from 2026-01-01T00:00:00Z --to 2026-01-02T00:00:00Z
# Limit results and output as JSON
ironflow audit trail run_abc123 --limit 100 --json

View the auth decision audit trail with optional filtering. Shows authentication and authorization decisions made by the platform.

Terminal window
ironflow audit auth-trail [flags]

Flags:

FlagShortTypeDefaultDescription
--orgstringOrganization ID (required)
--keystringFilter by API key ID
--actionstringFilter by action (e.g., functions:invoke)
--fromstringFrom timestamp (RFC3339)
--tostringTo timestamp (RFC3339)
--limitint50Maximum events to return
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Output:

TIMESTAMP EVENT TYPE DECISION PAYLOAD
10:30:15.123 auth.check allow {"action":"functions:invoke","key":"ak_abc"}
10:30:16.456 auth.check deny {"action":"runs:cancel","key":"ak_def"}
Total: 2 events

Examples:

Terminal window
# View all auth decisions for an organization
ironflow audit auth-trail --org org_default
# Filter by API key
ironflow audit auth-trail --org org_default --key ak_abc123
# Filter by action
ironflow audit auth-trail --org org_default --action functions:invoke
# Filter by time range with JSON output
ironflow audit auth-trail --org org_default --from 2026-01-01T00:00:00Z --json

Configuration file management.

Terminal window
ironflow config <subcommand>

Generate a starter ironflow.yaml configuration template.

Terminal window
ironflow config init [flags]

Flags:

FlagShortTypeDefaultDescription
--kindstringserverConfiguration kind: server, cluster, platform
--prodboolfalseGenerate production-ready template (with postgres, auth, observability)

Examples:

Terminal window
# Local dev (minimal Server)
ironflow config init
# Production single-node
ironflow config init --prod
# Multi-node cluster
ironflow config init --kind cluster
# Multi-tenant platform
ironflow config init --kind platform
# Pipe to a file
ironflow config init > ironflow.yaml
ironflow config init --kind cluster > ironflow.yaml

Ironflow Cloud operator commands (meta-cluster). These commands read from the meta-cluster Postgres directly (IRONFLOW_DATABASE_URL) or mint local signing artifacts. They are intended for the founder running on the meta box — they are not exposed to tenant operators.

Terminal window
ironflow cloud <subcommand> [flags]

Subcommands:

SubcommandDescription
provision-statusShow current status of a provisioning saga
cap-token mintMint an Ed25519 capability token for deprovision saga events
break-glassDecrypt a break-glass bearer blob for a cluster
snapshot decryptDecrypt a snapshot export blob for a cluster

Read the clusters row and the most recent provisioning_audit rows for a cluster. Connects directly to the meta-cluster Postgres via IRONFLOW_DATABASE_URL.

Terminal window
ironflow cloud provision-status <cluster_id> [flags]

Arguments:

ArgumentRequiredDescription
cluster_idYesThe cluster ID to query (e.g., clu_hooli)

Flags:

FlagShortTypeDefaultDescription
--jsonboolfalseOutput as JSON
--audit-limitint20Max provisioning_audit rows to show (capped at 1000)

Requires IRONFLOW_DATABASE_URL to be set.

Examples:

Terminal window
ironflow cloud provision-status clu_hooli
ironflow cloud provision-status clu_hooli --json
ironflow cloud provision-status clu_hooli --audit-limit 50

Mint an Ed25519-signed capability token that gates the cloud.deprovision-cluster.requested NATS event. The Ed25519 private key is loaded from IRONFLOW_CAP_TOKEN_PRIVATE_KEY_B64 (base64-encoded PKCS8 DER).

Terminal window
ironflow cloud cap-token mint <cluster_id> <customer_id> [flags]

Arguments:

ArgumentRequiredDescription
cluster_idYesCluster ID (e.g., clu_hooli)
customer_idYesCustomer ID (e.g., cust_01h2g3k4j5n6p7q8r9s0)

Flags:

FlagShortTypeDefaultDescription
--ttlduration10mToken time-to-live (max 10m; longer TTLs silently re-open replay)

Requires IRONFLOW_CAP_TOKEN_PRIVATE_KEY_B64 to be set.

Examples:

Terminal window
ironflow cloud cap-token mint clu_hooli cust_01h2g3k4j5n6p7q8r9s0
ironflow cloud cap-token mint clu_hooli cust_01h2g3k4j5n6p7q8r9s0 --ttl 5m

Decrypt a break-glass bearer blob fetched from the meta-cluster S3 bucket. The 32-byte meta-cluster KEK is loaded from IRONFLOW_MASTER_KEY_B64 (base64-encoded). The blob bytes are read from --blob-file (path) or stdin (default). The decrypted plaintext bearer is written to stdout with no trailing newline.

Terminal window
ironflow cloud break-glass <cluster_id> [flags]

Arguments:

ArgumentRequiredDescription
cluster_idYesCluster ID (e.g., clu_hooli)

Flags:

FlagShortTypeDefaultDescription
--blob-filestringPath to encrypted blob (default: stdin)

Requires IRONFLOW_MASTER_KEY_B64 to be set.

Examples:

Terminal window
# Fetch + decrypt via stdin pipe (preferred — blob never touches disk)
aws s3 cp s3://ironflow-break-glass-fsn/clu_hooli.enc - \
| ironflow cloud break-glass clu_hooli
# Decrypt a previously-saved blob file
ironflow cloud break-glass clu_hooli --blob-file /tmp/clu_hooli.enc

Decrypt a snapshot export blob produced by the deprovision saga’s snapshot_data step. The 32-byte meta-cluster KEK is loaded from IRONFLOW_MASTER_KEY_B64 (base64-encoded). The blob bytes are read from --blob-file (path) or stdin (default). The decrypted plaintext (typically a gzipped pg_dump) is written to stdout.

Terminal window
ironflow cloud snapshot decrypt <cluster_id> [flags]

Arguments:

ArgumentRequiredDescription
cluster_idYesCluster ID (e.g., clu_hooli)

Flags:

FlagShortTypeDefaultDescription
--blob-filestringPath to encrypted blob (default: stdin)
--max-bytesint64268435456 (256 MiB)Maximum blob bytes to read (held in RAM during decrypt; peak memory ≈ 2× blob size)

Requires IRONFLOW_MASTER_KEY_B64 to be set.

Examples:

Terminal window
# Fetch + decrypt via stdin pipe
aws s3 cp s3://ironflow-snapshots-fsn/exports/clu_hooli/run_xyz.tar.gz.enc - \
| ironflow cloud snapshot decrypt clu_hooli > dump.tar.gz
# Decrypt a previously-saved blob file with a 4 GiB cap
ironflow cloud snapshot decrypt clu_hooli \
--blob-file /tmp/clu_hooli-export.enc \
--max-bytes 4294967296 > dump.tar.gz

Manage circuit breakers that protect push endpoints from cascading failures. Circuit breaker state is persisted in NATS KV and shared across cluster nodes.

Terminal window
ironflow circuit-breaker <subcommand> [flags]

Aliases: cb

List all circuit breakers with their function IDs, endpoints, states, and failure counts.

Terminal window
ironflow circuit-breaker list [flags]

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL (default: IRONFLOW_SERVER_URL or http://localhost:9123)
--jsonboolfalseOutput as JSON

Examples:

Terminal window
# List all circuit breakers
ironflow circuit-breaker list
# JSON output
ironflow circuit-breaker list --json
# Custom server
ironflow circuit-breaker list -s http://localhost:9000

Output columns:

ColumnDescription
FUNCTION_IDThe function that owns this circuit breaker
ENDPOINTThe push endpoint URL being protected
STATECurrent state: closed, open, or half-open
FAILSNumber of consecutive failures
LAST_FAILURETimestamp of the most recent failure

Reset a circuit breaker back to closed state, allowing requests to flow to the endpoint again. Accepts either an endpoint URL or a function ID. If the argument contains :// it is treated as an endpoint URL; otherwise it is treated as a function ID.

Terminal window
ironflow circuit-breaker reset <endpoint-url | function-id> [flags]

Arguments:

ArgumentRequiredDescription
endpoint-urlYes*The endpoint URL of the breaker to reset
function-idYes*The function ID of the breaker to reset

*Provide either an endpoint URL or a function ID.

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL (default: IRONFLOW_SERVER_URL or http://localhost:9123)

Examples:

Terminal window
# Reset a circuit breaker by endpoint URL
ironflow circuit-breaker reset https://my-app.example.com/api/handler
# Reset a circuit breaker by function ID
ironflow circuit-breaker reset my-function-id

Inspect and cancel pending debounce entries for functions that collapse rapid-fire events into a single invocation. See the debounce how-to for background.

Terminal window
ironflow debounce <subcommand> [flags]

Subcommands:

SubcommandDescription
listList pending debounce entries (env-scoped)
cancelCancel one pending entry without firing it

List currently-armed debounce entries scoped to the request environment. Platform-scoped credentials see all envs.

Terminal window
ironflow debounce list [flags]

Flags:

LongShortTypeDefaultDescription
--jsonboolfalseOutput as JSON
--server-sstringServer URL (default: IRONFLOW_SERVER_URL or http://localhost:9123)

Examples:

Terminal window
ironflow debounce list
ironflow debounce list --json
ironflow debounce list -s http://localhost:9000

Output columns: FUNCTION_ID, KEY, FIRES_AT, PERIOD_MS, EVENT_ID.

Cancel one pending debounce entry by function ID and debounce key. The cancelled entry does not fire; the next event for the same key will start a fresh window.

Terminal window
ironflow debounce cancel <function-id> <debounce-key> [flags]

Flags:

LongShortTypeDefaultDescription
--envstringEnvironment ID (default: resolve from entry list if unambiguous)
--server-sstringServer URL (default: IRONFLOW_SERVER_URL or http://localhost:9123)

When --env is omitted, the command lists entries and matches uniquely on (function_id, debounce_key). Multiple matches across envs → error, pass --env to disambiguate. Debounce keys containing / or . are handled transparently (base64url encoded by the CLI on the wire).

Examples:

Terminal window
# Resolve env automatically when unambiguous
ironflow debounce cancel my-fn-id user-42
# Explicit env for tenant-scoped clarity
ironflow debounce cancel my-fn-id "build:repo-7" --env env_default
# Keys with special characters round-trip fine
ironflow debounce cancel my-fn-id "key.with.dots"

Deploy Ironflow to a Kubernetes cluster using Helm deployment templates.

Terminal window
ironflow deploy [flags]

Subcommands:

SubcommandDescription
upgradeUpgrade an existing deployment
statusShow deployment status
deleteDelete a deployment

Deploy a new Ironflow instance to Kubernetes.

Terminal window
ironflow deploy [flags]

Flags:

FlagShortTypeDefaultDescription
--templatestringDeployment template: small, medium, large (required)
--namestringHelm release name (required)
--namespace-nstringironflowKubernetes namespace to deploy into
--chartstringPath to Helm chart directory (auto-detected if omitted)
--kubeconfigstringPath to kubeconfig file (defaults to current kubectl context)
--hetzner-locationstringHetzner datacenter location (e.g. fsn1, nbg1, hel1). Installs Traefik ingress with Hetzner LB optimizations and applies the full kube-prometheus-stack config (persistent storage, Slack alert routing, Healthchecks.io dead-man’s switch, Grafana admin from external secret).
--setstring[]Set Helm values (repeatable)

Examples:

Terminal window
# Small deployment for dev/evaluation
ironflow deploy --template small --name dev
# Medium deployment for staging
ironflow deploy --template medium --name staging
# Large deployment with external dependencies
ironflow deploy --template large --name prod \
--set externalDatabase.url=postgres://... \
--set externalNats.url=nats://...
# Deploy to a custom namespace
ironflow deploy --template medium --name staging --namespace my-ns
# Deploy with Hetzner load balancer
ironflow deploy --template medium --name prod --hetzner-location fsn1
# Deploy targeting a specific cluster
ironflow deploy --template medium --name prod \
--kubeconfig ~/.kube/clusters/hetzner-prod.yaml

Upgrade an existing Ironflow deployment.

Terminal window
ironflow deploy upgrade [flags]

Flags: Same as ironflow deploy (initial deploy).

Examples:

Terminal window
ironflow deploy upgrade --template medium --name staging

Show status of an Ironflow deployment.

Terminal window
ironflow deploy status [flags]

Flags:

FlagShortTypeDefaultDescription
--namestringHelm release name (required)
--namespace-nstringironflowKubernetes namespace
--kubeconfigstringPath to kubeconfig file (defaults to current kubectl context)
--watch-wboolfalseWatch pod status after showing deployment status

Examples:

Terminal window
ironflow deploy status --name staging
ironflow deploy status --name prod --watch

Delete an Ironflow deployment.

Terminal window
ironflow deploy delete [flags]

Flags:

FlagShortTypeDefaultDescription
--namestringHelm release name (required)
--namespace-nstringironflowKubernetes namespace
--kubeconfigstringPath to kubeconfig file (defaults to current kubectl context)

Examples:

Terminal window
ironflow deploy delete --name staging

Emit a named event to the server. If any registered functions have triggers matching the event name, runs will be created for them.

Terminal window
ironflow emit <event-name> [flags]

By default, the event is emitted asynchronously — the command prints the event ID and any triggered runs, then exits immediately. Use --wait to block until all triggered runs complete.

Arguments:

ArgumentRequiredDescription
event-nameYesThe event name (e.g., order.placed)

Flags:

FlagShortTypeDefaultDescription
--data-dstringInline JSON data payload (defaults to {})
--data-file-fstringPath to JSON file containing data payload
--metadata-mstring[]Key=value metadata pairs (repeatable)
--wait-wboolfalseBlock until all matched runs complete
--timeout-tduration30sMax wait time (only with --wait)
--versionint1Event schema version
--jsonboolfalseOutput as JSON instead of human-friendly text
--server-sstringServer URL override

Data input:

Data comes from exactly one source. If multiple are detected, the command errors:

  1. --data '{...}' — Inline JSON string
  2. --data-file path.json — Read from file
  3. Stdin — Automatically detected when input is piped

If none are provided, data defaults to {} (empty object).

Examples:

Terminal window
# Emit with inline data
ironflow emit order.placed --data '{"order_id": "123", "total": 99.99}'
# Emit from a file
ironflow emit user.signup --data-file ./test-user.json
# Pipe from stdin
echo '{"batch_id": "daily"}' | ironflow emit cron.daily
# Signal event with no data
ironflow emit cache.invalidate
# Wait for all runs to complete
ironflow emit order.placed --data '{"order_id": "123"}' --wait
# Wait with custom timeout
ironflow emit video.uploaded --data-file ./meta.json --wait --timeout 120s
# JSON output for scripting
ironflow emit order.placed --data '{}' --wait --json | jq '.results[0]'
# Attach metadata
ironflow emit order.placed --data '{}' -m source=cli -m env=dev
# Emit with a specific event version
ironflow emit order.placed --data '{"order_id": "123"}' --version 2

Output (async):

Event emitted: evt_01HN8K3X5Y (order.placed)
Triggered 2 run(s): run_abc123, run_def456

Output (—wait):

Emitting event "order.placed" and waiting for completion (timeout: 30s)...
✓ process-order RUN_STATUS_COMPLETED 1200ms {"order_confirmed":true}
✓ send-notification RUN_STATUS_COMPLETED 300ms {"email_sent":true}

Failed or timed-out runs produce a non-zero exit code.


Manage environments.

Terminal window
ironflow env <subcommand> [flags]

Environments provide logical isolation within a single Ironflow instance. All data (functions, events, runs, streams, projections) is scoped to the environment that created it. API keys are managed separately via ironflow apikey — see API Keys.

Ironflow creates one default environment on first boot:

NameID
defaultenv_default

Subcommands:

List all environments with their IDs.

Terminal window
ironflow env list [--server URL]

Create a new environment.

Terminal window
ironflow env create <name> [--server URL] [--project PROJECT_ID]
FlagTypeDefaultDescription
--projectstringProject ID to associate with the environment

Creates an isolated namespace within your Ironflow instance. The new environment starts empty — no functions, events, or runs.

Delete an environment by ID.

Terminal window
ironflow env delete <id> [--server URL]

Deletes the environment. The default environment (env_default) cannot be deleted.

All env subcommands accept --server / -s to override the server URL.

Examples:

Terminal window
# List environments
ironflow env list
# Create a new environment for a specific app
ironflow env create my-app
# Delete a custom environment
ironflow env delete env_my-app

Manage event schemas and test upcasters.

Terminal window
ironflow event <subcommand> [flags]

Subcommands:

Register a JSON schema for an event type at a specific version.

Terminal window
ironflow event schema register <event-name> [flags]

Arguments:

ArgumentRequiredDescription
event-nameYesThe event name (e.g., order.created)

Flags:

FlagShortTypeDefaultDescription
--versionintSchema version (required)
--filestringPath to JSON schema file
--schemastringInline JSON schema string
--descriptionstringSchema description
--server-sstringServer URL override

One of --file or --schema is required. Cannot use both.

Examples:

Terminal window
ironflow event schema register order.created --version 1 --file schema.json
ironflow event schema register order.created --version 1 --schema '{"type":"object"}'
ironflow event schema register order.created --version 2 --file schema-v2.json --description "Added address field"

List registered event schemas.

Terminal window
ironflow event schema list [flags]

Flags:

FlagShortTypeDefaultDescription
--eventstringFilter by event name
--limitint100Maximum number of schemas to return
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Output:

EVENT VERSION DESCRIPTION REGISTERED
order.created 1 Order created event 2025-01-15 12:00:05
order.created 2 Added address field 2025-01-20 09:30:00

Examples:

Terminal window
ironflow event schema list
ironflow event schema list --event order.created
ironflow event schema list --json

Get detailed information about a registered event schema.

Terminal window
ironflow event schema get <event-name> [flags]

Arguments:

ArgumentRequiredDescription
event-nameYesThe event name to look up

Flags:

FlagShortTypeDefaultDescription
--versionint0Schema version (0 = latest)
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Output:

Event: order.created
Version: 2
Description: Added address field
Registered: 2025-01-20 09:30:00
Schema:
{"type":"object","properties":{"id":{"type":"string"},"address":{"type":"object"}}}

Examples:

Terminal window
ironflow event schema get order.created
ironflow event schema get order.created --version 2
ironflow event schema get order.created --json

Delete a registered event schema.

Terminal window
ironflow event schema delete <event-name> [flags]

Arguments:

ArgumentRequiredDescription
event-nameYesThe event name to delete

Flags:

FlagShortTypeDefaultDescription
--versionintSchema version (required)
--server-sstringServer URL override

Output:

Deleted schema order.created (v1)

Test how an event would be transformed between schema versions.

Terminal window
ironflow event upcast <event-name> [flags]

Arguments:

ArgumentRequiredDescription
event-nameYesThe event name to upcast

Flags:

FlagShortTypeDefaultDescription
--fromintSource version (required)
--tointTarget version (required)
--datastringEvent data as JSON
--data-filestringPath to JSON file with data
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Data input follows the same rules as emit (flag vs file vs stdin).

Output:

Steps applied:
FROM TO DESCRIPTION
1 2 added priority field
Result data:
{
"orderId": "123",
"customerId": "456",
"priority": "normal"
}

Examples:

Terminal window
ironflow event upcast order.created --from 1 --to 2 --data '{"orderId":"123"}'
ironflow event upcast order.created --from 1 --to 2 --data-file event.json
ironflow event upcast order.created --from 1 --to 3 --data '{}' --json

List and inspect registered functions.

Terminal window
ironflow function <subcommand> [flags]

List all registered functions with their triggers and execution mode.

Terminal window
ironflow function list [flags]

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override
--jsonboolfalseOutput as JSON
--limitint100Maximum number of functions to return

Output:

ID TRIGGERS MODE
stripe-handler stripe.payment.* push
order-process order.created pull

Get detailed information about a registered function.

Terminal window
ironflow function get <function-id> [flags]

Arguments:

ArgumentRequiredDescription
function-idYesThe function ID to look up

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override
--jsonboolfalseOutput as JSON

Output:

ID: stripe-handler
Name: Stripe Handler
Description: Handles Stripe webhook events
Mode: push
Endpoint: http://localhost:3000/api/ironflow
Triggers: stripe.payment.*

Examples:

Terminal window
ironflow function list
ironflow function list --json
ironflow function get stripe-handler
ironflow function get stripe-handler --json

Create a new Ironflow project from a template.

Terminal window
ironflow init <project-name> [flags]

Arguments:

ArgumentRequiredDescription
project-nameYesName of the new project

Flags:

FlagShortTypeDefaultDescription
--template-tstringquickstartProject template (quickstart, go-quickstart)
--skip-installboolfalseSkip installing dependencies
--modulestringGo module path for go-quickstart template

Examples:

Terminal window
ironflow init my-app
ironflow init my-app --template go-quickstart
ironflow init my-app --template go-quickstart --module github.com/user/my-app
ironflow init my-app --skip-install

Inspect a workflow run with the TUI debugger.

Terminal window
ironflow inspect <run_id> [flags]

Opens an interactive terminal UI for stepping through a completed or failed workflow run. This is a read-only viewer — it does not re-execute the workflow.

Arguments:

ArgumentRequiredDescription
run_idYesThe run ID to inspect

Flags:

FlagTypeDefaultDescription
--serverstringIRONFLOW_SERVER_URL or http://localhost:9123Ironflow server URL
--dapboolfalseStart DAP server for VS Code debugging
--dap-portint4711DAP server port
--atstringInspect run state at a specific timestamp (ISO 8601)
--replayboolfalseStep through run events frame-by-frame
--all-eventsboolfalseInclude all events in replay mode (including step.started)

Examples:

Terminal window
# Interactive TUI debugger
ironflow inspect run_abc123
# DAP mode for VS Code
ironflow inspect run_abc123 --dap
# Custom server
ironflow inspect run_abc123 --server http://prod-server:9123
# Time-travel: inspect run state at a specific point in time
ironflow inspect run_abc123 --at "2024-01-15T10:30:00Z"
# Time-travel: step through events frame-by-frame (DVR replay)
ironflow inspect run_abc123 --replay
# Time-travel: replay with all events including step.started
ironflow inspect run_abc123 --replay --all-events

Directly invoke a function by ID.

Terminal window
ironflow invoke <function-id> [flags]

By default, the command is synchronous — it blocks until the function completes and prints the output. Use --no-wait to fire-and-forget.

Under the hood, invoke emits a synthetic event ironflow.invoke.<function-id> and auto-registers a trigger for it on the target function if one doesn’t already exist.

Arguments:

ArgumentRequiredDescription
function-idYesThe function to invoke (e.g., process-order)

Flags:

FlagShortTypeDefaultDescription
--data-dstringInline JSON input data (defaults to {})
--data-file-fstringPath to JSON file containing input data
--metadata-mstring[]Key=value metadata pairs (repeatable)
--no-waitboolfalseFire-and-forget (don’t wait for result)
--timeout-tduration30sMax wait time
--jsonboolfalseOutput as JSON instead of human-friendly text
--server-sstringServer URL override

Data input follows the same rules as emit (flag vs file vs stdin, error on conflict, default {}).

Examples:

Terminal window
# Invoke and wait for result (default)
ironflow invoke process-order --data '{"order_id": "123"}'
# Fire-and-forget
ironflow invoke send-notification --data '{"user_id": "456"}' --no-wait
# With custom timeout
ironflow invoke generate-report --data '{}' --timeout 120s
# Pipe from file
cat complex-input.json | ironflow invoke generate-report
# JSON output
ironflow invoke process-order --data '{"order_id": "123"}' --json

Output (sync):

Invoking process-order (timeout: 30s)...
✓ process-order completed in 1200ms
Output: {"order_confirmed":true}

Output (—no-wait):

Invoked process-order (event: evt_01HN8K3X5Y)
Run ID: run_abc123

Start the Model Context Protocol (MCP) server for AI assistant integration.

Terminal window
ironflow mcp [flags]

AI assistants like Claude Code, Cursor, and Windsurf can use this to interact with your Ironflow server directly from the IDE. The MCP server runs on stdio.

By default, only read operations are enabled. Use --allow-writes to enable write operations like emitting events and invoking functions.

Flags:

FlagTypeDefaultDescription
--server-urlstringhttp://localhost:9123Ironflow server URL
--api-keystringAPI key for authentication (or IRONFLOW_API_KEY)
--allow-writesboolfalseEnable write operations (emit events, invoke)

Examples:

Terminal window
# Start read-only MCP server
ironflow mcp
# Start with write access
ironflow mcp --allow-writes
# Custom server URL
ironflow mcp --server-url http://prod:9123 --api-key ifkey_...

Manage organizations. Create, list, get, and delete organizations.

Terminal window
ironflow org <subcommand> [flags]

Subcommands:

SubcommandDescription
createCreate a new organization
listList all organizations
getGet organization details
deleteDelete an organization

Create a new organization with the given name.

Terminal window
ironflow org create <name> [flags]

Arguments:

ArgumentRequiredDescription
nameYesName for the new organization

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override

Examples:

Terminal window
ironflow org create my-org
ironflow org create my-org --server http://localhost:9000

List all organizations with their IDs, names, and creation dates.

Terminal window
ironflow org list [flags]

Flags:

FlagShortTypeDefaultDescription
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Output:

ID NAME CREATED
org_abc123 my-org 2026-01-01T00:00:00Z

Examples:

Terminal window
ironflow org list
ironflow org list --json

Get detailed information about an organization.

Terminal window
ironflow org get <id> [flags]

Arguments:

ArgumentRequiredDescription
idYesOrganization ID to query

Flags:

FlagShortTypeDefaultDescription
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Output:

ID: org_abc123
Name: my-org
Created At: 2026-01-01T00:00:00Z
Updated At: 2026-01-15T12:00:00Z

Examples:

Terminal window
ironflow org get org_abc123
ironflow org get org_abc123 --json

Delete an organization by its ID.

Terminal window
ironflow org delete <id> [flags]

Arguments:

ArgumentRequiredDescription
idYesOrganization ID to delete

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override

Examples:

Terminal window
ironflow org delete org_abc123

Inspect and manage the transactional outbox (issue #487). Today the only exposed subtree is dlq — operator tooling for the dead-letter table when a publish has failed past its retry budget. See the outbox explanation and the DLQ runbook for background and triage flow.

Terminal window
ironflow outbox <subcommand> [flags]

Subcommands:

SubcommandDescription
dlqList, requeue, or discard rows in the outbox dead-letter table

List rows in the outbox dead-letter table for one environment, newest first. Rows land in this table after the outbox worker exhausts its retry budget (default 10 attempts with exponential backoff). The underlying event row in events is unaffected — only the unpublished NATS delivery is stuck.

--env is required (or set IRONFLOW_ENV). There is no default. Silent defaulting during incident triage could hide rows in the env you actually need to inspect.

Terminal window
ironflow outbox dlq list [flags]

Flags:

FlagShortTypeDefaultDescription
--envstringEnvironment name (required unless IRONFLOW_ENV is set)
--limitint50Max rows to return (1-500)
--offsetint0Row offset for pagination
--jsonboolfalseOutput as JSON (structured for jq-based triage)
--server-sstringServer URL override

Examples:

Terminal window
# Inspect the DLQ for prod, tab-formatted
ironflow outbox dlq list --env prod
# With IRONFLOW_ENV set
IRONFLOW_ENV=prod ironflow outbox dlq list
# Structured output for scripting
ironflow outbox dlq list --env prod --limit 100 --json | jq '.items[] | {event_id, topic, last_error}'

Move a dead-letter row back to the live outbox table with attempts=0 so the worker picks it up on the next tick. Use this after fixing the root cause (NATS restored, stream recreated, credentials rotated, etc.).

Terminal window
ironflow outbox dlq requeue <event-id> [flags]

Arguments:

ArgumentRequiredDescription
event-idYesThe event_id of the dead-letter entry to requeue

Flags:

FlagShortTypeDefaultDescription
--envstringEnvironment name (required unless IRONFLOW_ENV is set)
--server-sstringServer URL override

Examples:

Terminal window
ironflow outbox dlq requeue evt_abc123 --env prod
# Bulk requeue from a list output
ironflow outbox dlq list --env prod --json \
| jq -r '.items[].event_id' \
| while read id; do ironflow outbox dlq requeue "$id" --env prod; done

Permanently delete a dead-letter row. The underlying events row is not deleted — only the unpublished outbox entry. Use this when a payload is unrecoverable (oversized, poison, etc.) or when you have confirmed downstream consumers don’t need the event. Destructive; prompts for confirmation unless --yes is passed.

Terminal window
ironflow outbox dlq discard <event-id> [flags]

Arguments:

ArgumentRequiredDescription
event-idYesThe event_id of the dead-letter entry to discard

Flags:

FlagShortTypeDefaultDescription
--envstringEnvironment name (required unless IRONFLOW_ENV is set)
--yesboolfalseSkip the confirmation prompt
--server-sstringServer URL override

Examples:

Terminal window
ironflow outbox dlq discard evt_abc123 --env prod # prompts y/N
ironflow outbox dlq discard evt_abc123 --env prod --yes # non-interactive

Manage the Ironflow platform: users, tenants, roles, and audit log.

Requires platform credentials (via ironflow platform login) or IRONFLOW_API_KEY.

Terminal window
ironflow platform <subcommand> [flags]

Bootstrap the first platform admin user. Refuses if any platform user already exists. Uses IRONFLOW_API_KEY for authentication (bootstrap runs before platform login is available).

Terminal window
ironflow platform create-admin --email <email> --name <name> [flags]
FlagShortTypeDefaultDescription
--emailstringAdmin email (required)
--namestringAdmin display name (required)
--server-sstringServer URL override

Password is read interactively from the terminal.

Examples:

Terminal window
ironflow platform create-admin --email admin@example.com --name "Admin"

Authenticate with email and password to obtain a platform JWT token. The token is stored in ~/.config/ironflow/credentials.json (or $IRONFLOW_CONFIG_DIR/credentials.json).

Terminal window
ironflow platform login --email <email> [flags]
FlagShortTypeDefaultDescription
--emailstringPlatform user email (required)
--server-sstringServer URL override

Examples:

Terminal window
ironflow platform login --email admin@example.com
ironflow platform login --email admin@example.com --server http://localhost:9000

Manage platform users.

Terminal window
ironflow platform users <subcommand> [flags]

List all platform users with their IDs, emails, names, and active status.

Terminal window
ironflow platform users list [flags]
FlagShortTypeDefaultDescription
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Examples:

Terminal window
ironflow platform users list
ironflow platform users list --json

Create a new platform user with email, name, and password.

Terminal window
ironflow platform users create --email <email> --name <name> [flags]
FlagShortTypeDefaultDescription
--emailstringUser email (required)
--namestringUser display name (required)
--role-ids[]stringRole IDs to assign
--server-sstringServer URL override

Password is read interactively from the terminal.

Examples:

Terminal window
ironflow platform users create --email user@example.com --name "User"
ironflow platform users create --email user@example.com --name "User" --role-ids role_abc

Delete a platform user by ID.

Terminal window
ironflow platform users delete <id> [flags]
FlagShortTypeDefaultDescription
--server-sstringServer URL override

Examples:

Terminal window
ironflow platform users delete usr_abc123

Platform API keys are managed through the unified ironflow apikey command with the --platform flag. See ironflow apikey above.

Terminal window
# Create a platform key
ironflow apikey create my-platform-key --platform
# List platform keys
ironflow apikey list --platform
# Rotate a platform key
ironflow apikey rotate ak_abc123
# Delete a platform key
ironflow apikey delete ak_abc123

Manage tenants.

Terminal window
ironflow platform tenants <subcommand> [flags]

List all tenants with their IDs, names, and creation dates.

Terminal window
ironflow platform tenants list [flags]
FlagShortTypeDefaultDescription
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Examples:

Terminal window
ironflow platform tenants list
ironflow platform tenants list --json

Provision a new tenant.

Terminal window
ironflow platform tenants provision --name <name> [flags]
FlagShortTypeDefaultDescription
--namestringTenant name (required)
--server-sstringServer URL override

Examples:

Terminal window
ironflow platform tenants provision --name my-tenant

Delete a tenant by ID.

Terminal window
ironflow platform tenants delete <id> [flags]
FlagShortTypeDefaultDescription
--server-sstringServer URL override

Examples:

Terminal window
ironflow platform tenants delete tnt_abc123

Manage platform roles.

Terminal window
ironflow platform roles <subcommand> [flags]

List all platform roles with their IDs, names, and default status.

Terminal window
ironflow platform roles list [flags]
FlagShortTypeDefaultDescription
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Examples:

Terminal window
ironflow platform roles list
ironflow platform roles list --json

Create a new platform role with the given name.

Terminal window
ironflow platform roles create <name> [flags]
FlagShortTypeDefaultDescription
--policy-ids[]stringPolicy IDs to attach
--server-sstringServer URL override

Examples:

Terminal window
ironflow platform roles create my-role
ironflow platform roles create my-role --policy-ids pol_abc

Delete a platform role by ID.

Terminal window
ironflow platform roles delete <id> [flags]
FlagShortTypeDefaultDescription
--server-sstringServer URL override

Examples:

Terminal window
ironflow platform roles delete role_abc123

Query the platform audit log with optional filters.

Terminal window
ironflow platform audit [flags]
FlagShortTypeDefaultDescription
--event-typestringFilter by event type
--fromstringFilter events from this date (inclusive)
--tostringFilter events to this date (inclusive)
--cursorstringPagination cursor
--limitint0Maximum number of events to return
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Examples:

Terminal window
ironflow platform audit
ironflow platform audit --event-type user.created --limit 50
ironflow platform audit --from 2024-01-01 --to 2024-12-31 --json

Manage authorization policies.

Terminal window
ironflow policy <subcommand> [flags]

Policies define access control rules with an effect (allow/deny), actions, resource IRN patterns, and optional CEL conditions. See Custom Roles & CEL Policies for full details.

Create a new authorization policy.

Terminal window
ironflow policy create [flags]

Flags:

FlagShortTypeDefaultDescription
--namestringPolicy name (required)
--effectstringallow or deny (required)
--actionsstringComma-separated action patterns (required)
--resourcesstringComma-separated IRN resource patterns (required)
--conditionstringCEL condition expression (optional)
--bypass-self-lockout-preflightboolfalseSkip the self-lockout preflight (break-glass; audited)
--bypass-reasonstringRequired when --bypass-self-lockout-preflight is set
--server-sstringServer URL override

Output:

Created policy: allow-prod-reads (id: pol_x1y2z3)

List all policies, optionally filtered by organization.

Terminal window
ironflow policy list [flags]

Flags:

FlagShortTypeDefaultDescription
--orgstringFilter by organization
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Output:

ID NAME EFFECT ACTIONS RESOURCES
pol_x1y2z3 allow-prod-reads allow functions:list,runs:read irn:ironflow:*:*:prod:*
pol_a4b5c6 deny-prod-writes deny functions:register,functions:invoke irn:ironflow:*:*:prod:*

Get detailed information about a policy.

Terminal window
ironflow policy get <id> [flags]

Arguments:

ArgumentRequiredDescription
idYesPolicy ID

Flags:

FlagShortTypeDefaultDescription
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Output:

ID: pol_x1y2z3
Name: allow-prod-reads
Effect: allow
Actions: functions:list,runs:read,events:subscribe
Resources: irn:ironflow:*:*:prod:*
Condition: request.environment == "prod"

Patch fields on an existing policy. Only flags you provide are sent to the server.

Terminal window
ironflow policy update <id> [flags]

Arguments:

ArgumentRequiredDescription
idYesPolicy ID

Flags:

FlagShortTypeDefaultDescription
--namestringNew name
--effectstringNew effect (allow or deny)
--actionsstringNew comma-separated actions
--resourcesstringNew comma-separated resource IRNs
--conditionstringNew CEL condition
--clear-conditionboolfalseClear the existing CEL condition (sends empty string)
--bypass-self-lockout-preflightboolfalseSkip the self-lockout preflight (break-glass; audited)
--bypass-reasonstringRequired when --bypass-self-lockout-preflight is set
--server-sstringServer URL override

Delete a policy by its ID.

Terminal window
ironflow policy delete <id> [flags]

Arguments:

ArgumentRequiredDescription
idYesPolicy ID

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override

Output:

Policy deleted

Compile and evaluate a CEL condition (saved or inline) against caller-supplied request and subject activation maps. Nothing is persisted; mirrors POST /api/v1/policies/dry-run.

Terminal window
ironflow policy test [flags]

Flags:

FlagShortTypeDefaultDescription
--policy-idstringSaved policy ID whose condition to test
--conditionstringInline CEL condition to test (overrides saved condition)
--requeststringRequest activation map as inline JSON
--subjectstringSubject activation map as inline JSON
--request-filestringPath to request activation JSON file
--subject-filestringPath to subject activation JSON file
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Either --policy-id or --condition is required. Inline JSON wins when both inline and file flags are passed.

Output:

Condition: subject.org == "acme"
Matched: true

Show full version history for a policy, newest first. Each row is a full snapshot for client-side diffing.

Terminal window
ironflow policy versions list <policy_id> [flags]

Flags:

FlagShortTypeDefaultDescription
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Forward-save a prior version’s snapshot as a new version. History is append-only — rollback never rewrites past rows.

Terminal window
ironflow policy rollback <policy_id> <version> [flags]

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override

List installable policy templates visible to your tenant: tenant-private bundles plus platform-published bundles.

Terminal window
ironflow policy template list [flags]

Flags:

FlagShortTypeDefaultDescription
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Install a template bundle into your org. Validation runs against every spec; one bad condition or name collision rejects the whole install (no partial bundles).

Terminal window
ironflow policy template install <template_id> [flags]

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override

Examples:

Terminal window
# Create an allow policy for read-only access in production
ironflow policy create --name allow-prod-reads --effect allow \
--actions "functions:list,runs:read,events:subscribe" \
--resources "irn:ironflow:*:*:prod:*"
# Create a deny policy for writes in production
ironflow policy create --name deny-prod-writes --effect deny \
--actions "functions:register,functions:invoke,events:emit" \
--resources "irn:ironflow:*:*:prod:*"
# Create a policy with a CEL condition (business hours only)
ironflow policy create --name staging-business-hours --effect allow \
--actions "*" --resources "irn:ironflow:*:*:staging:*" \
--condition "request.timestamp.getHours() >= 9 && request.timestamp.getHours() < 17"
# List all policies
ironflow policy list
ironflow policy list --org org_default --json
# Update a policy's condition
ironflow policy update pol_x1y2z3 --condition "subject.org == 'acme'"
# Test a policy condition without saving
ironflow policy test --policy-id pol_x1y2z3 \
--request '{"action":"read"}' \
--subject '{"id":"u1","roles":["admin"]}'
# Browse and roll back versions
ironflow policy versions list pol_x1y2z3
ironflow policy rollback pol_x1y2z3 2
# Install a template bundle
ironflow policy template list
ironflow policy template install tpl_admin_basics
# Break-glass: bypass the self-lockout preflight (audited)
ironflow policy update pol_x1y2z3 --effect deny \
--bypass-self-lockout-preflight \
--bypass-reason "incident-217 emergency lockout recovery"
# Delete a policy
ironflow policy delete pol_x1y2z3

Manage projects. Projects group related environments within an organization (e.g., a microservice or team boundary). The resource hierarchy is Organization → Project → Environment.

Terminal window
ironflow project <subcommand> [flags]

Subcommands:

SubcommandDescription
createCreate a new project
listList all projects
deleteDelete a project

Create a new project with the given name within the current organization.

Terminal window
ironflow project create <name> [flags]

Arguments:

ArgumentRequiredDescription
nameYesName for the new project

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override

Examples:

Terminal window
ironflow project create my-project
ironflow project create backend-service --server http://localhost:9000

List all projects with their IDs, names, and creation dates.

Terminal window
ironflow project list [flags]

Flags:

FlagShortTypeDefaultDescription
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Output:

ID NAME CREATED
proj_default_default default 2026-01-01T00:00:00Z

Examples:

Terminal window
ironflow project list
ironflow project list --json

Delete a project by its ID.

Terminal window
ironflow project delete <id> [flags]

Arguments:

ArgumentRequiredDescription
idYesProject ID to delete

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override

Examples:

Terminal window
ironflow project delete proj_abc123

Manage projections: list, check status, trigger and cancel rebuilds.

Terminal window
ironflow projection <subcommand> [flags]

Subcommands:

List all registered projections with their mode, status, and event count.

Terminal window
ironflow projection list [flags]

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override
--jsonboolfalseOutput as JSON

Output:

NAME MODE STATUS EVENTS LAST SEQ UPDATED
orders-by-customer managed active 3 1523 2m ago
inventory-tracker external rebuilding 2 0 15s ago

Show detailed status for a projection, including rebuild progress if one is running.

Terminal window
ironflow projection status <name> [flags]

Arguments:

ArgumentRequiredDescription
nameYesThe projection name

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override
--jsonboolfalseOutput as JSON

Output (active projection):

Name: orders-by-customer
Status: active
Mode: managed
Last Event: 1523
Lag: 0
Updated: 2m ago

Output (rebuilding projection):

Name: orders-by-customer
Status: rebuilding
Mode: managed
Last Event: 0
Lag: 1200
Updated: 15s ago
Rebuild Job:
Job ID: rebuild-abc123
Status: running
Progress: 65.0%
Processed: 65000 / 100000 events
Started: 2m30s ago
ETA: 1m15s

Start a rebuild of a projection. Resets state and replays events from the event log.

Terminal window
ironflow projection rebuild <name> [flags]

Arguments:

ArgumentRequiredDescription
nameYesThe projection to rebuild

Flags:

FlagShortTypeDefaultDescription
--fromstringStart replay from this event ID
--tostringStop replay at this event ID
--partitionstringOnly rebuild this partition
--dry-runboolfalseEstimate work without starting rebuild
--server-sstringServer URL override
--jsonboolfalseOutput as JSON

Output:

Rebuild started
Job ID: rebuild-abc123
Projection: orders-by-customer
Status: running
Total Events: 100000

Output (—dry-run):

Dry run — rebuild not started
Job ID: rebuild-abc123
Projection: orders-by-customer
Status: dry_run
Total Events: 100000

Examples:

Terminal window
# Full rebuild
ironflow projection rebuild orders-by-customer
# Partial rebuild from a specific event
ironflow projection rebuild orders-by-customer --from evt_123
# Rebuild a specific partition
ironflow projection rebuild orders-by-customer --partition customer-123
# Preview what a rebuild would do
ironflow projection rebuild orders-by-customer --dry-run
# Rebuild with event range
ironflow projection rebuild orders-by-customer --from evt_123 --to evt_456

Cancel an in-progress rebuild. Previous state is preserved.

Terminal window
ironflow projection rebuild cancel <name> [flags]

Arguments:

ArgumentRequiredDescription
nameYesThe projection to cancel rebuild for

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override

Output:

Rebuild cancelled for projection "orders-by-customer" (status: cancelled)

Get the current state and metadata of a projection.

Terminal window
ironflow projection get <name> [flags]

Arguments:

ArgumentRequiredDescription
nameYesThe projection name

Flags:

FlagShortTypeDefaultDescription
--partitionstringPartition key
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Output:

Name: order-totals
Mode: managed
Version: 15
Last Event ID: evt_01HN8K3X5Y
Last Event At: 2m ago
State: {
"total_orders": 42,
"total_revenue": 12500.00
}

Examples:

Terminal window
ironflow projection get order-totals
ironflow projection get order-totals --partition tenant-123
ironflow projection get order-totals --json

Pause a running projection. It will stop processing events until resumed.

Terminal window
ironflow projection pause <name> [flags]

Arguments:

ArgumentRequiredDescription
nameYesThe projection name

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override

Output:

Paused projection "order-totals" (status: paused)

Resume a paused projection. It will continue processing events from where it left off.

Terminal window
ironflow projection resume <name> [flags]

Arguments:

ArgumentRequiredDescription
nameYesThe projection name

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override

Output:

Resumed projection "order-totals" (status: active)

Unregister and delete a projection. Does not delete data written to external stores.

Terminal window
ironflow projection delete <name> [flags]

Arguments:

ArgumentRequiredDescription
nameYesThe projection name

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override

Output:

Deleted projection "old-projection"

Create a new SQL projection that builds a read model from event streams.

Terminal window
ironflow projection create <name> [flags]

Arguments:

ArgumentRequiredDescription
nameYesThe projection name

Flags:

FlagShortTypeDefaultDescription
--sqlstringTable DDL for the projection (CREATE TABLE ...) (required unless --sql-file)
--sql-filestringPath to a file containing the table DDL (required unless --sql)
--eventstring[]Event name to subscribe to (repeatable) (required)
--event-handlerstring[]Per-event SQL handler in event_name=SQL format (repeatable) (required)
--descriptionstringProjection description
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

One of --sql or --sql-file is required. Cannot use both. At least one --event and one --event-handler are also required.

Output:

Created SQL projection "order-totals" (status: active)

Examples:

Terminal window
ironflow projection create order-totals \
--sql "CREATE TABLE proj_order_totals (order_id TEXT PRIMARY KEY, amount NUMERIC)" \
--event "order.placed" \
--event-handler "order.placed=INSERT INTO proj_order_totals (order_id, amount) VALUES (:entity_id, :data.total)"
ironflow projection create order-totals \
--sql-file projection.sql \
--event "order.placed" \
--event-handler "order.placed=INSERT INTO proj_order_totals (order_id, amount) VALUES (:entity_id, :data.total)" \
--description "Order totals"
ironflow projection create board \
--sql "CREATE TABLE proj_board (id TEXT PRIMARY KEY, title TEXT, status TEXT)" \
--event "issue.created" --event "issue.status_changed" \
--event-handler "issue.created=INSERT INTO proj_board (id, title, status) VALUES (:entity_id, :data.title, 'OPEN')" \
--event-handler "issue.status_changed=UPDATE proj_board SET status = :data.to WHERE id = :entity_id" \
--json

Watch real-time updates for a projection via WebSocket.

Terminal window
ironflow projection watch <name> [flags]

Arguments:

ArgumentRequiredDescription
nameYesThe projection name to watch

Flags:

FlagShortTypeDefaultDescription
--server-sstringws://localhost:9123/wsWebSocket server URL
--replay-rint0Number of historical events to replay
--json-jboolfalseOutput events as JSON
--metadata-mboolfalseInclude event metadata

Examples:

Terminal window
ironflow projection watch order-totals
ironflow projection watch order-totals --replay 10
ironflow projection watch order-totals --json

Block until a projection has processed events up to --min-seq (NATS sequence on the PUBSUB stream). Used for read-your-writes after a write returned a sequence in AppendResult.

Terminal window
ironflow projection wait <name> --min-seq <n> [flags]

Arguments:

ArgumentRequiredDescription
nameYesThe projection name

Flags:

FlagShortTypeDefaultDescription
--server-sstringIRONFLOW_SERVER_URLServer URL
--min-sequint64Target NATS sequence the projection must reach (required)
--timeoutduration30sMaximum wait duration. Server caps at 60s unary, 300s with --stream.
--partitionstring""Scope wait to a single partition (managed projections)
--streamboolfalseUse streaming RPC (#476) — raises the cap to 300s and emits progress + heartbeat frames so long waits survive proxies/LBs with short idle timeouts.
--jsonboolfalseOutput as JSON

Exit codes:

CodeMeaning
0Projection caught up within timeout
1Timed out
2Error (projection not found, paused/rebuilding, bad input, network)

Examples:

Terminal window
ironflow projection wait order-view --min-seq 1234
ironflow projection wait order-view --min-seq 1234 --timeout 10s
ironflow projection wait order-view --min-seq 1234 --partition tenant-1 --json
# Streaming — progress lines print as the cursor advances:
ironflow projection wait order-view --min-seq 1234 --stream --timeout 5m

Wait until the given projection has processed the event identified by <event-id>. The server resolves the event ID to its NATS sequence via events.nats_seq and waits on that.

Terminal window
ironflow projection wait-for-event <event-id> --projection <name> [flags]

Arguments:

ArgumentRequiredDescription
event-idYesThe event ID

Flags:

FlagShortTypeDefaultDescription
--server-sstringIRONFLOW_SERVER_URLServer URL
--projectionstringProjection name to wait on (required)
--timeoutduration30sMaximum wait duration. Server caps at 60s.
--partitionstring""Scope wait to a single partition (managed projections)
--jsonboolfalseOutput as JSON

Exit codes: same as projection wait. Events written before migration 010 may have a NULL nats_seq and return exit code 2; in that case fall back to projection wait --min-seq using a sequence from a fresh write.

Examples:

Terminal window
ironflow projection wait-for-event evt_abc --projection order-view
ironflow projection wait-for-event evt_abc --projection order-view --timeout 10s --json

Wait on multiple projections concurrently. All items share a single timeout and a single atomic capacity reservation on the server. Max 16 items per batch.

Terminal window
ironflow projection wait-batch --file <path> [flags]

The input file is a JSON array of items:

[
{"name": "order-view", "minSeq": 42, "partition": "tenant-1"},
{"name": "inventory", "minSeq": 42}
]

Use --file - to read from stdin.

Flags:

FlagShortTypeDefaultDescription
--server-sstringIRONFLOW_SERVER_URLServer URL
--filestringPath to JSON items file, or - for stdin (required)
--timeoutduration30sMaximum wait duration. Server caps at 60s.
--jsonboolfalseOutput as JSON

Exit codes:

CodeMeaning
0All items caught up within timeout
1At least one item timed out (none errored)
2At least one item errored, or bad input / network

Examples:

Terminal window
ironflow projection wait-batch --file items.json
jq '...' | ironflow projection wait-batch --file - --timeout 10s --json

Provision infrastructure for Ironflow (Kubernetes cluster creation).

Terminal window
ironflow provision <subcommand> [flags]

Subcommands:

SubcommandDescription
createCreate a Kubernetes cluster
statusCheck infrastructure status
destroyDestroy provisioned infrastructure

Create a Kubernetes cluster on the specified provider. The --name flag sets the cluster name — all cloud resources (servers, networks, firewalls, SSH keys, load balancers) are named after it. A kubeconfig is saved to ~/.kube/clusters/<provider>-<name>.yaml.

Terminal window
ironflow provision create [flags]

Flags:

FlagShortTypeDefaultDescription
--providerstringInfrastructure provider: hetzner, k3d (required)
--namestringCluster name (required). Used to name all cloud resources and the saved kubeconfig file.
--templatestringCluster size: small, medium, large (required)

Examples:

Terminal window
# Hetzner Cloud (real infrastructure)
ironflow provision create --provider hetzner --template medium --name ironflow
# Kubeconfig saved to ~/.kube/clusters/hetzner-ironflow.yaml
# Multiple clusters with different names
ironflow provision create --provider hetzner --template small --name staging
ironflow provision create --provider hetzner --template medium --name prod
# Kubeconfigs: ~/.kube/clusters/hetzner-staging.yaml, ~/.kube/clusters/hetzner-prod.yaml
# Local k3d (Docker Desktop)
ironflow provision create --provider k3d --template small --name dev
ironflow provision create --provider k3d --template medium --name dev

Check status of provisioned infrastructure.

Terminal window
ironflow provision status [flags]

Flags:

FlagShortTypeDefaultDescription
--providerstringInfrastructure provider: hetzner, k3d (required)
--namestringCluster name (required)

Examples:

Terminal window
ironflow provision status --provider hetzner --name ironflow
ironflow provision status --provider k3d --name dev

Destroy provisioned infrastructure.

Terminal window
ironflow provision destroy [flags]

Flags:

FlagShortTypeDefaultDescription
--providerstringInfrastructure provider: hetzner, k3d (required)
--namestringCluster name (required)

Examples:

Terminal window
ironflow provision destroy --provider hetzner --name ironflow
ironflow provision destroy --provider k3d --name dev

Manage custom roles for enterprise authorization.

Terminal window
ironflow role <subcommand> [flags]

Custom roles extend the three built-in roles (admin, developer, viewer) with organization-scoped roles that can have policies attached. See Custom Roles & CEL Policies for full details.

Create a new custom role in an organization.

Terminal window
ironflow role create <name> [flags]

Arguments:

ArgumentRequiredDescription
nameYesRole name

Flags:

FlagShortTypeDefaultDescription
--orgstringOrganization ID (required)
--server-sstringServer URL override

Output:

Created role: billing-team (id: role_a1b2c3d4)

List all roles, optionally filtered by organization.

Terminal window
ironflow role list [flags]

Flags:

FlagShortTypeDefaultDescription
--orgstringFilter by organization
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Output:

ID NAME ORG_ID DEFAULT
role_a1b2c3d4 admin org_default true
role_e5f6g7h8 developer org_default true
role_i9j0k1l2 viewer org_default true
role_m3n4o5p6 billing org_default false

Get detailed information about a role.

Terminal window
ironflow role get <id> [flags]

Arguments:

ArgumentRequiredDescription
idYesRole ID

Flags:

FlagShortTypeDefaultDescription
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Output:

ID: role_a1b2c3d4
Name: billing-team
Org ID: org_default
Default: false

Delete a custom role by its ID.

Terminal window
ironflow role delete <id> [flags]

Arguments:

ArgumentRequiredDescription
idYesRole ID

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override

Output:

Role deleted

Assign a policy to a role.

Terminal window
ironflow role assign-policy <role_id> <policy_id> [flags]

Arguments:

ArgumentRequiredDescription
role_idYesRole ID
policy_idYesPolicy ID

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override

Output:

Policy assigned to role

Remove a policy from a role.

Terminal window
ironflow role remove-policy <role_id> <policy_id> [flags]

Arguments:

ArgumentRequiredDescription
role_idYesRole ID
policy_idYesPolicy ID

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override

Output:

Policy removed from role

Examples:

Terminal window
# Create a custom role
ironflow role create billing-team --org org_default
# List all roles
ironflow role list
ironflow role list --org org_default --json
# Get role details
ironflow role get role_a1b2c3d4
# Assign a policy to a role
ironflow role assign-policy role_a1b2c3d4 pol_x1y2z3
# Remove a policy from a role
ironflow role remove-policy role_a1b2c3d4 pol_x1y2z3
# Delete a custom role
ironflow role delete role_a1b2c3d4

List and inspect workflow runs.

Terminal window
ironflow run <subcommand> [flags]

List workflow runs with optional filtering.

Terminal window
ironflow run list [flags]

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override
--functionstringFilter by function ID
--statusstringFilter by status (pending, running, completed, failed, cancelled)
--limitint50Maximum number of runs to return
--jsonboolfalseOutput as JSON

Output:

ID FUNCTION STATUS STARTED
run-1 stripe-handler completed 2025-01-15 12:00:05
run-2 order-process failed 2025-01-15 11:59:30

Get detailed information about a specific workflow run.

Terminal window
ironflow run get <run-id> [flags]

Arguments:

ArgumentRequiredDescription
run-idYesThe run ID to look up

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override
--jsonboolfalseOutput as JSON

Output:

ID: run-abc123
Function: stripe-handler
Status: completed
Mode: push
Event: evt_01HN8K3X5Y
Started: 2025-01-15T12:00:05Z
Ended: 2025-01-15T12:00:06Z
Duration: 1.2s

Cancel a running or pending workflow run.

Terminal window
ironflow run cancel <run-id> [flags]

Arguments:

ArgumentRequiredDescription
run-idYesThe run ID to cancel

Flags:

FlagShortTypeDefaultDescription
--reasonstringCancellation reason
--server-sstringServer URL override

Output:

Canceled run run-abc123 (status: cancelled)

Examples:

Terminal window
ironflow run list
ironflow run list --function stripe-handler --status failed
ironflow run list --limit 10 --json
ironflow run get run_abc123
ironflow run get run_abc123 --json
ironflow run cancel run_abc123
ironflow run cancel run_abc123 --reason "no longer needed"

Pause a running workflow at the next step boundary for inspection and injection.

Terminal window
ironflow run pause <run-id> [flags]

If the run is currently executing, sets a pause flag that is consumed at the next step boundary. If the run is already paused (sleeping or waiting for an event), it immediately transitions to an injection pause.

Arguments:

ArgumentRequiredDescription
run-idYesThe run ID to pause

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override

Output:

Run run-abc123: paused

Examples:

Terminal window
# Pause a running workflow
ironflow run pause run_abc123
# Pause against a different server
ironflow run pause run_abc123 --server http://prod:9123

View completed steps and their outputs for a run paused for injection.

Terminal window
ironflow run paused-state <run-id> [flags]

Only works on runs with pause_reason = "injection". Shows each completed step’s ID, name, whether it was injected, and its output. Also displays the pause reason and next step hint if available.

Arguments:

ArgumentRequiredDescription
run-idYesThe paused run ID to inspect

Flags:

FlagShortTypeDefaultDescription
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Output:

Pause reason: injection
Next step: send-notification
ID NAME INJECTED OUTPUT
step_001 validate-input {"valid":true}
step_002 process-order {"order_id":"123","total":99.99}

Examples:

Terminal window
# View paused state
ironflow run paused-state run_abc123
# JSON output for scripting
ironflow run paused-state run_abc123 --json

Modify the output of a completed step while a run is paused for injection.

Terminal window
ironflow run inject <run-id> <step-id> [flags]

Replaces the step’s output with new data. The original output is preserved in original_output for audit purposes. An audit event (step.injected) is emitted if the function has recording enabled.

Arguments:

ArgumentRequiredDescription
run-idYesThe paused run ID
step-idYesThe completed step ID to modify

Flags:

FlagShortTypeDefaultDescription
--outputstringNew JSON output for the step (required)
--reasonstringReason for the injection (optional)
--server-sstringServer URL override

Output:

Injected step step_002
Previous output: {"order_id":"123","total":99.99}

Examples:

Terminal window
# Inject modified output
ironflow run inject run_abc123 step_002 --output '{"order_id":"123","total":89.99}'
# Inject with a reason for the audit trail
ironflow run inject run_abc123 step_002 \
--output '{"corrected": true}' \
--reason "Fix calculation error"

Resume a paused or failed run. When resuming an injection-paused run, clears the pause state and re-dispatches from where it left off.

Terminal window
ironflow run resume <run-id> [flags]

Arguments:

ArgumentRequiredDescription
run-idYesThe run ID to resume

Flags:

FlagShortTypeDefaultDescription
--from-stepstringResume from a specific step ID
--server-sstringServer URL override

Examples:

Terminal window
# Resume a paused run
ironflow run resume run_abc123
# Resume from a specific step
ironflow run resume run_abc123 --from-step step_002
# Typical scoped injection workflow
ironflow run pause run_abc123
ironflow run paused-state run_abc123
ironflow run inject run_abc123 step_002 --output '{"fixed": true}' --reason "correct value"
ironflow run resume run_abc123

Manage encrypted secrets. Secrets are environment-scoped and write-only — values can be set but are never returned by the CLI or API.

List all secrets in the current environment (metadata only — values are never shown).

Terminal window
ironflow secret list [--server URL] [--env ENV]
FlagShortDescriptionDefault
--server-sServer URL$IRONFLOW_SERVER_URL or http://localhost:9123
--env-eEnvironment name$IRONFLOW_ENV or default

Create or update a secret.

Terminal window
ironflow secret set <name> <value> [--server URL] [--env ENV] [--description DESC]
FlagShortDescriptionDefault
--server-sServer URL$IRONFLOW_SERVER_URL or http://localhost:9123
--env-eEnvironment name$IRONFLOW_ENV or default
--description-dHuman-readable description(none)

Get metadata for a specific secret (value is never shown).

Terminal window
ironflow secret get <name> [--server URL] [--env ENV]
FlagShortDescriptionDefault
--server-sServer URL$IRONFLOW_SERVER_URL or http://localhost:9123
--env-eEnvironment name$IRONFLOW_ENV or default

Delete a secret.

Terminal window
ironflow secret delete <name> [--server URL] [--env ENV]
FlagShortDescriptionDefault
--server-sServer URL$IRONFLOW_SERVER_URL or http://localhost:9123
--env-eEnvironment name$IRONFLOW_ENV or default

Examples:

Terminal window
# List secrets (metadata only)
ironflow secret list
# Set a secret
ironflow secret set API_KEY sk-abc123 --description "OpenAI API key"
# Set a secret in a specific environment
ironflow secret set DB_PASSWORD mypass --env production
# Get metadata for a secret
ironflow secret get API_KEY
# Delete a secret
ironflow secret delete API_KEY

Start the Ironflow server with embedded NATS JetStream, database, and web dashboard.

Terminal window
ironflow serve [flags]

Flags:

FlagShortTypeDefaultDescription
--config-fstringPath to ironflow.yaml configuration file
--port-pint9123HTTP server port
--db-dstringironflow.dbSQLite database path
--open-oboolfalseOpen dashboard in browser after startup
--nats-store-dirstring(auto-derived from --db)Embedded NATS JetStream storage directory. Default: {dirname(--db)}/ironflow-nats. Pass empty (--nats-store-dir="") for memory mode opt-out. With Postgres or :memory: SQLite, must be set explicitly or ironflow serve fails fast. (Or set NATS_STORE_DIR; explicit flag wins over env var.)
--nats-urlstring(none)External NATS URL — nats://host:4222, tls://host:4222, or comma-separated seeds (or set NATS_URL). Requires PostgreSQL (IRONFLOW_DATABASE_URL).
--nats-credsstring(none)Path to NATS .creds file for JWT/NKey authentication (or set NATS_CREDS_FILE).
--node-idstring(random UUID)Stable node identifier for cluster coordination (or set IRONFLOW_NODE_ID).
--devboolfalseEnable dev mode: bypasses all authentication (API + dashboard)
--pprofboolfalseEnable pprof debug endpoints on a separate listener at :6060
--bootstrap-key-filestring(auto-derived)Path to write the first-boot admin API key (mode 0400). Default: <db-dir>/.ironflow_bootstrap_key.json. Production meta-cluster systemd sets /run/ironflow/bootstrap-key.json.

What it starts:

  1. Embedded NATS JetStream (messaging)
  2. Database — SQLite by default, PostgreSQL if IRONFLOW_DATABASE_URL is set
  3. Workflow engine (step execution, memoization, retry)
  4. PubSub bridge (real-time WebSocket event delivery)
  5. Consumer group manager (load-balanced event delivery)
  6. HTTP server with ConnectRPC API and web dashboard

Examples:

Terminal window
# Start with defaults (SQLite, port 9123)
ironflow serve
# Custom port, open dashboard
ironflow serve --port 8080 --open
# PostgreSQL backend
IRONFLOW_DATABASE_URL="postgres://user:pass@localhost:5432/ironflow" ironflow serve
# Persistent NATS storage (default since #614 — derived from --db path)
# To override the auto-derived path:
ironflow serve --nats-store-dir ./data/nats
# Memory-mode opt-out (tests, demos, ephemeral CI)
ironflow serve --nats-store-dir=""
# Multi-node cluster (external NATS + PostgreSQL required)
IRONFLOW_DATABASE_URL="postgres://user:pass@localhost:5432/ironflow" \
ironflow serve --nats-url nats://nats:4222 --node-id node-1
# Cluster with NATS authentication
IRONFLOW_DATABASE_URL="postgres://..." \
ironflow serve --nats-url nats://nats:4222 --nats-creds /etc/ironflow/node.creds
# Auth is always on — API key from bootstrap is printed on first boot
# Custom bootstrap key file (production meta-cluster)
ironflow serve --bootstrap-key-file /run/ironflow/bootstrap-key.json
# Dev mode — skip auth for local development
ironflow serve --dev

The --dev flag disables all authentication for local development:

Terminal window
ironflow serve --dev

In dev mode:

  • API requests are granted admin-level access without an API key
  • Dashboard loads without requiring login
  • All requests use org_default, env_default, and the admin role
  • A prominent warning is shown in the startup banner

Warning: Never use --dev in production. It is a CLI flag only (no env var) to ensure it is an intentional choice on every startup.


Server management commands.

Terminal window
ironflow server <subcommand> [flags]

Display server health, version, and runtime information.

Terminal window
ironflow server info [flags]

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override
--jsonboolfalseOutput as JSON

Examples:

Terminal window
# Show server info
ironflow server info
# JSON output
ironflow server info --json
# Connect to a different server
ironflow server info --server http://localhost:9000

Output:

Server: http://localhost:9123
Version: 0.5.0
Status: healthy
Uptime: 2h15m0s
Go: go1.25.0
Functions: 3 registered
Runs: 1 active
Workers: 2 connected

Execute a read-only SQL query against the Ironflow database.

Terminal window
ironflow sql <query> [flags]

Queries are automatically scoped to the current environment. Only SELECT statements are allowed. Mutation keywords (INSERT, UPDATE, DELETE, DROP, etc.) are rejected.

Arguments:

ArgumentRequiredDescription
queryYesSQL SELECT query to execute

Flags:

FlagShortTypeDefaultDescription
--formatstringtableOutput format: table, json, csv, jsonl
--timeoutint5000Query timeout in milliseconds
--max-rowsint1000Maximum rows to return
--server-sstringServer URL override

Available tables: events, runs, steps, functions, environments, projection_registry, projection_state

Environment scoping: Queries are automatically filtered to the current environment via temporary views. The environment is determined by the IRONFLOW_ENV env var, or defaults to default.

Examples:

Terminal window
# Count events by name
ironflow sql "SELECT name, COUNT(*) AS total FROM events GROUP BY name"
# Find failed runs
ironflow sql "SELECT id, status FROM runs WHERE status = 'failed' LIMIT 10"
# Export events as JSON
ironflow sql "SELECT * FROM events WHERE entity_id = 'order-123'" --format json
# CSV output for spreadsheets
ironflow sql "SELECT id, name FROM functions" --format csv
# JSONL for streaming processing
ironflow sql "SELECT * FROM events" --format jsonl | jq '.name'

Output (table):

id name entity_id
evt_001 order.placed order-123
evt_002 order.paid order-123

Manage entity streams for event sourcing.

Terminal window
ironflow stream <subcommand> [flags]

Entity streams store domain events per entity with optimistic concurrency control.

Subcommands:

Append a domain event to an entity stream.

Terminal window
ironflow stream append <entity-id> [flags]

Arguments:

ArgumentRequiredDescription
entity-idYesThe entity ID to append the event to

Flags:

FlagShortTypeDefaultDescription
--typestringEntity type (e.g., Order, User)
--eventstringEvent name (required)
--data-dstringEvent data as JSON string
--data-file-fstringPath to JSON file with event data
--expected-versionint64-1Expected stream version (-1=skip, 0=new, N=exact)
--versionint1Event schema version
--idempotency-keystringIdempotency key for deduplication
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Data input follows the same rules as emit (flag vs file vs stdin, error on conflict).

Examples:

Terminal window
# Append an event
ironflow stream append order-1 --type Order --event order.placed --data '{"amount": 100}'
# Append from file
ironflow stream append order-1 --type Order --event order.paid --data-file payment.json
# With optimistic concurrency
ironflow stream append order-1 --type Order --event order.shipped --expected-version 2
# Pipe from stdin
echo '{"status": "done"}' | ironflow stream append order-1 --type Order --event order.completed

Output:

Event appended: evt_01HN8K3X5Y
Entity: order-1
Version: 3

Read events from an entity stream.

Terminal window
ironflow stream read <entity-id> [flags]

Arguments:

ArgumentRequiredDescription
entity-idYesThe entity ID to read

Flags:

FlagShortTypeDefaultDescription
--from-versionint640Start reading from this version
--limitint100Maximum number of events to return
--directionstringforwardRead direction (forward or backward)
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Output:

VERSION NAME DATA TIMESTAMP
1 order.placed {"amount":100} 2025-01-15 12:00:05
2 order.paid {"payment_id":"pay_123"} 2025-01-15 12:01:30

Examples:

Terminal window
ironflow stream read order-1
ironflow stream read order-1 --limit 10
ironflow stream read order-1 --from-version 5 --direction backward
ironflow stream read order-1 --json

Get metadata about an entity stream.

Terminal window
ironflow stream info <entity-id> [flags]

Arguments:

ArgumentRequiredDescription
entity-idYesThe entity ID to inspect

Flags:

FlagShortTypeDefaultDescription
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Output:

Entity ID: order-1
Entity Type: Order
Version: 3
Events: 3
Created: 2025-01-15T12:00:05Z
Updated: 2025-01-15T12:01:30Z

List entity streams with optional filtering by type.

Terminal window
ironflow stream list [flags]

Flags:

FlagShortTypeDefaultDescription
--typestringFilter by entity type
--limitint50Maximum number of streams
--offsetint0Offset for pagination
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Output:

ENTITY_ID TYPE VERSION EVENTS UPDATED
order-1 Order 3 3 2m ago
order-2 Order 1 1 5m ago
user-1 User 2 2 1h ago

Watch real-time events for an entity stream via WebSocket.

Terminal window
ironflow stream subscribe <entity-id> [flags]

Arguments:

ArgumentRequiredDescription
entity-idYesThe entity ID to subscribe to

Flags:

FlagShortTypeDefaultDescription
--server-sstringws://localhost:9123/ws (derived from IRONFLOW_SERVER_URL if set)WebSocket server URL
--replay-rint0Number of historical events to replay
--json-jboolfalseOutput events as JSON
--metadata-mboolfalseInclude event metadata

Examples:

Terminal window
ironflow stream subscribe order-123
ironflow stream subscribe order-123 --replay 10
ironflow stream subscribe order-123 --json

Subscribe to real-time events via WebSocket.

Terminal window
ironflow subscribe [patterns...] [flags]

Connects to the server’s WebSocket endpoint and streams events matching the given NATS-style patterns.

Arguments:

ArgumentRequiredDescription
patternsYes (1+)NATS-style topic patterns to subscribe to

Flags:

FlagShortTypeDefaultDescription
--server-sstringws://localhost:9123/ws (derived from IRONFLOW_SERVER_URL if set)WebSocket server URL
--replay-rint0Number of historical events to replay
--json-jboolfalseOutput events as JSON (one per line)
--metadata-mboolfalseInclude event metadata (timestamp, sequence)

Examples:

Terminal window
# Subscribe to all run events
ironflow subscribe "system.run.>"
# Subscribe to user events
ironflow subscribe "events:order.placed"
# Multiple patterns with replay
ironflow subscribe --replay 10 "system.run.>" "events:>"

Provision and list tenant organizations. Tenants provide multi-tenancy by atomically creating an organization, built-in roles, and a default environment.

Terminal window
ironflow tenant <subcommand> [flags]

Subcommands:

SubcommandDescription
provisionProvision a new tenant organization
listList all tenants

Atomically create an organization, built-in roles, and a default environment.

Terminal window
ironflow tenant provision [flags]

Flags:

FlagShortTypeDefaultDescription
--namestringOrganization name (required)
--envstringEnvironment name (default: production)
--server-sstringServer URL override

Output:

Created org: Acme Corp (org_abc123)
Created env: production (env_def456)
Admin API Key: ak_abc123...

Examples:

Terminal window
# Provision a new tenant with default environment
ironflow tenant provision --name "Acme Corp"
# Provision with a custom environment name
ironflow tenant provision --name "Acme Corp" --env staging

List all tenant organizations with their environment and key counts.

Terminal window
ironflow tenant list [flags]

Flags:

FlagShortTypeDefaultDescription
--jsonboolfalseOutput as JSON
--server-sstringServer URL override

Output:

ID NAME ENVS KEYS CREATED
org_abc123 Acme Corp 1 2 2026-01-01T00:00:00Z
org_def456 Widget Inc 2 3 2026-02-15T00:00:00Z

Examples:

Terminal window
ironflow tenant list
ironflow tenant list --json

Manage developer pub/sub topics: list topics, view statistics, and publish messages.

Terminal window
ironflow topic <subcommand> [flags]

Topics provide lightweight service-to-service messaging without triggering functions. See the Topics guide for full details.

List all active developer pub/sub topics.

Terminal window
ironflow topic list [flags]

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override
--jsonboolfalseOutput as JSON

Output:

NAME MESSAGES CONSUMERS
order.processed 42 2
user.signup 15 1

Show detailed statistics for a specific topic.

Terminal window
ironflow topic stats <topic> [flags]

Arguments:

ArgumentRequiredDescription
topicYesTopic name (e.g., order.processed)

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override
--jsonboolfalseOutput as JSON

Output:

Topic: order.processed
Messages: 42
Consumers: 2
Lag: 5
First Seq: 1
Last Seq: 42

Publish a message to a developer pub/sub topic.

Terminal window
ironflow topic publish <topic> [flags]

Arguments:

ArgumentRequiredDescription
topicYesTopic name (e.g., order.processed)

Flags:

FlagShortTypeDefaultDescription
--data-dstringJSON data to publish
--data-file-fstringPath to JSON file with data
--idempotency-keystringIdempotency key for deduplication
--server-sstringServer URL override

Data can be provided via --data flag, --data-file flag, or piped via stdin.

Output:

Published to order.processed (event_id=evt_abc123, seq=43)

Examples:

Terminal window
# List all topics
ironflow topic list
ironflow topic list --json
# View topic statistics
ironflow topic stats order.processed
ironflow topic stats order.processed --json
# Publish a message
ironflow topic publish order.processed --data '{"orderId": "123", "status": "shipped"}'
# Publish from file
ironflow topic publish order.processed --data-file payload.json
# Publish from stdin
echo '{"orderId": "123"}' | ironflow topic publish order.processed
# Publish with idempotency key
ironflow topic publish order.processed --data '{"orderId": "123"}' --idempotency-key order-123-shipped

Validate an ironflow.yaml configuration file without starting the server. Checks syntax, schema, environment variable references, and kind-specific rules.

Terminal window
ironflow validate [flags]

Flags:

FlagShortTypeDefaultDescription
--config-fstringPath to ironflow.yaml configuration file (required)

Output:

Validating ironflow.yaml...
Kind: Server
Storage: sqlite (ironflow.db)
NATS: embedded (memory mode)
Auth: DEV MODE (disabled)
License: not configured (Core edition)
Tracing: disabled
Metrics: disabled
✓ Valid. Ready to boot with: ironflow serve -f ironflow.yaml

Examples:

Terminal window
ironflow validate -f ironflow.yaml
ironflow validate -f /etc/ironflow/production.yaml

Print version and build information.

Terminal window
ironflow version

Output:

ironflow version v0.1.0
go: go1.25.0
os/arch: darwin/arm64

Manage webhook sources and deliveries.

Terminal window
ironflow webhook <subcommand> [flags]

Webhook sources receive HTTP payloads from external providers (Stripe, GitHub, etc.), validate signatures, deduplicate deliveries, and emit Ironflow events. See the Webhooks guide for full details.

List all registered webhook sources.

Terminal window
ironflow webhook list [flags]

Flags:

FlagShortTypeDefaultDescription
--server-sstringServer URL override
--jsonboolfalseOutput as JSON

Output:

ID EVENT PREFIX TYPE VERIFY HEADER ALGORITHM CREATED
stripe webhook/stripe api Stripe-Signature hmac-sha256 2025-01-15 12:00:05
github webhook/github sdk 2025-01-15 11:00:00

List webhook deliveries with optional filtering by provider and status.

Terminal window
ironflow webhook deliveries [flags]

Status is color-coded: green=accepted, red=rejected/failed, yellow=deduplicated.

Flags:

FlagShortTypeDefaultDescription
--providerstringFilter by source/provider ID
--statusstringFilter by status (accepted, rejected, failed, deduplicated)
--limitint20Maximum number of deliveries to return
--server-sstringServer URL override
--jsonboolfalseOutput as JSON

Output:

ID SOURCE STATUS EVENT ID EXTERNAL ID ERROR CREATED
del_abc123 stripe accepted evt_def456 evt_stripe_1 2025-01-15 12:00:05
del_abc124 stripe deduplicated evt_stripe_1 2025-01-15 12:00:06
del_abc125 github rejected missing signature 2025-01-15 12:01:00

Send a test webhook delivery to the webhook endpoint.

Terminal window
ironflow webhook test --provider <id> --payload <json> [flags]

Sends a raw HTTP POST to /api/v1/webhooks/{provider} to simulate an incoming webhook delivery. The payload must be valid JSON.

Flags:

FlagShortTypeDefaultDescription
--providerstringWebhook provider/source ID (required)
--payloadstringJSON payload to send (required)
--server-sstringServer URL override

Output (success):

Webhook delivered successfully (HTTP 200)
{
"status": "accepted",
"delivery_id": "del_abc123",
"event_id": "evt_def456",
"run_ids": ["run_789"]
}

Examples:

Terminal window
# List webhook sources
ironflow webhook list
ironflow webhook list --json
# View deliveries
ironflow webhook deliveries
ironflow webhook deliveries --provider stripe
ironflow webhook deliveries --provider stripe --status rejected
ironflow webhook deliveries --limit 100 --json
# Send a test webhook
ironflow webhook test --provider stripe \
--payload '{"type":"charge.succeeded","data":{"amount":2000}}'
# Test against a different server
ironflow webhook test --provider github \
--payload '{"action":"push"}' --server http://localhost:9000

These are the environment variables used by CLI client commands. For server-side configuration (database, NATS, dashboard auth, etc.), see Configuration.

VariableDefaultDescription
IRONFLOW_SERVER_URLhttp://localhost:9123Server URL for all client commands
IRONFLOW_API_KEY(none)API key sent as Authorization: Bearer header for auth
IRONFLOW_ENVdefaultEnvironment name for scoping queries and operations
IRONFLOW_CONFIG_DIR~/.config/ironflowDirectory for storing platform credentials (credentials.json)
LOG_LEVELwarn (info for serve)Log level: trace, debug, info, warn, error, fatal