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]Global Behavior
Section titled “Global Behavior”- 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 byIRONFLOW_SERVER_URL(default:http://localhost:9123) - API key authentication is supported via
IRONFLOW_API_KEYwhen the server has auth enabled - The
--as-org <org_id>global flag allows platform users to impersonate an organization. Requires platform credentials (viaironflow platform login). Sends the platform JWT and sets theX-Ironflow-Orgheader on requests. - The
--verbose/-vglobal flag enables debug-level diagnostic logging on stderr. By default, CLI commands run atwarnlevel (quiet). Theservecommand defaults toinfolevel so startup messages remain visible. TheLOG_LEVELenv 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 viaironflow platform login. Falls back toIRONFLOW_API_KEYif 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 viaIRONFLOW_DATABASE_URLrather than the Ironflow server API. - Exit code
0indicates success;1indicates an error
Commands
Section titled “Commands”ironflow apikey
Section titled “ironflow apikey”Manage API keys for authentication. Create, list, delete, and rotate API keys.
ironflow apikey <subcommand> [flags]Subcommands:
| Subcommand | Description |
|---|---|
create | Create a new API key |
list | List all API keys |
delete | Delete an API key |
rotate | Rotate an API key |
ironflow apikey create
Section titled “ironflow apikey create”Create a new API key with the given name. Returns the key value which must be saved immediately.
ironflow apikey create <name> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
name | Yes | Name for the new API key |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--env | string | Environment ID to scope the key to | ||
--role | string[] | Role ID to assign (can be specified multiple times) | ||
--expires | string | Expiration duration (e.g. 720h for 30 days) | ||
--platform | bool | false | Create a platform-scoped key (ifplatform_ prefix) | |
--server | -s | string | Server URL override |
Examples:
# Create a basic API keyironflow apikey create my-key
# Create a key with rolesironflow apikey create my-key --role role_abc123 --role role_def456
# Create a key scoped to an environment with expirationironflow apikey create my-key --env env_abc123 --expires 720h
# Create a platform key for cross-tenant operationsironflow apikey create my-platform-key --platformironflow apikey list
Section titled “ironflow apikey list”List all API keys with their IDs, names, prefixes, roles, and timestamps.
ironflow apikey list [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--json | bool | false | Output as JSON | |
--platform | bool | false | List only platform-scoped keys | |
--server | -s | string | Server URL override |
Output:
ID NAME PREFIX ROLES CREATED LAST USED EXPIRESak_abc123 my-key ak_abc role_abc123 2026-01-01T00:00:00Z 2026-03-01T12:00:00Z -Examples:
# List all API keysironflow apikey list
# List platform keys onlyironflow apikey list --platform
# List as JSONironflow apikey list --jsonironflow apikey delete
Section titled “ironflow apikey delete”Delete an API key by its ID. The key is immediately revoked.
ironflow apikey delete <id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
id | Yes | API key ID to delete |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override |
Examples:
ironflow apikey delete ak_abc123ironflow apikey rotate
Section titled “ironflow apikey rotate”Rotate an API key by its ID. Creates a new key with the same name, environment, and roles. The old key is immediately revoked.
ironflow apikey rotate <id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
id | Yes | API key ID to rotate |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override |
Examples:
ironflow apikey rotate ak_abc123ironflow audit
Section titled “ironflow audit”View and query history inspection (audit trail) records for workflow runs and auth decisions. Uses the ConnectRPC API.
ironflow audit <subcommand> [flags]Subcommands:
| Subcommand | Description |
|---|---|
trail | View history inspection (audit trail) for a workflow run |
auth-trail | View auth decision audit trail (Enterprise) |
ironflow audit trail
Section titled “ironflow audit trail”View the audit trail for a specific workflow run with optional filtering.
ironflow audit trail <run-id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
run-id | Yes | Workflow run ID to query |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--type | string | Filter by event type (e.g., step.completed) | ||
--from | string | From timestamp (RFC3339) | ||
--to | string | To timestamp (RFC3339) | ||
--limit | int | 50 | Maximum events to return | |
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL override |
Output:
TIMESTAMP EVENT TYPE STEP ID PAYLOAD10: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 eventsExamples:
# View all audit events for a runironflow audit trail run_abc123
# Filter by event typeironflow audit trail run_abc123 --type step.completed
# Filter by time rangeironflow audit trail run_abc123 --from 2026-01-01T00:00:00Z --to 2026-01-02T00:00:00Z
# Limit results and output as JSONironflow audit trail run_abc123 --limit 100 --jsonironflow audit auth-trail
Section titled “ironflow audit auth-trail”View the auth decision audit trail with optional filtering. Shows authentication and authorization decisions made by the platform.
ironflow audit auth-trail [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--org | string | Organization ID (required) | ||
--key | string | Filter by API key ID | ||
--action | string | Filter by action (e.g., functions:invoke) | ||
--from | string | From timestamp (RFC3339) | ||
--to | string | To timestamp (RFC3339) | ||
--limit | int | 50 | Maximum events to return | |
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL override |
Output:
TIMESTAMP EVENT TYPE DECISION PAYLOAD10: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 eventsExamples:
# View all auth decisions for an organizationironflow audit auth-trail --org org_default
# Filter by API keyironflow audit auth-trail --org org_default --key ak_abc123
# Filter by actionironflow audit auth-trail --org org_default --action functions:invoke
# Filter by time range with JSON outputironflow audit auth-trail --org org_default --from 2026-01-01T00:00:00Z --jsonironflow config
Section titled “ironflow config”Configuration file management.
ironflow config <subcommand>ironflow config init
Section titled “ironflow config init”Generate a starter ironflow.yaml configuration template.
ironflow config init [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--kind | string | server | Configuration kind: server, cluster, platform | |
--prod | bool | false | Generate production-ready template (with postgres, auth, observability) |
Examples:
# Local dev (minimal Server)ironflow config init
# Production single-nodeironflow config init --prod
# Multi-node clusterironflow config init --kind cluster
# Multi-tenant platformironflow config init --kind platform
# Pipe to a fileironflow config init > ironflow.yamlironflow config init --kind cluster > ironflow.yamlironflow cloud
Section titled “ironflow cloud”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.
ironflow cloud <subcommand> [flags]Subcommands:
| Subcommand | Description |
|---|---|
provision-status | Show current status of a provisioning saga |
cap-token mint | Mint an Ed25519 capability token for deprovision saga events |
break-glass | Decrypt a break-glass bearer blob for a cluster |
snapshot decrypt | Decrypt a snapshot export blob for a cluster |
ironflow cloud provision-status
Section titled “ironflow cloud provision-status”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.
ironflow cloud provision-status <cluster_id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
cluster_id | Yes | The cluster ID to query (e.g., clu_hooli) |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--json | bool | false | Output as JSON | |
--audit-limit | int | 20 | Max provisioning_audit rows to show (capped at 1000) |
Requires IRONFLOW_DATABASE_URL to be set.
Examples:
ironflow cloud provision-status clu_hooliironflow cloud provision-status clu_hooli --jsonironflow cloud provision-status clu_hooli --audit-limit 50ironflow cloud cap-token mint
Section titled “ironflow cloud cap-token mint”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).
ironflow cloud cap-token mint <cluster_id> <customer_id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
cluster_id | Yes | Cluster ID (e.g., clu_hooli) |
customer_id | Yes | Customer ID (e.g., cust_01h2g3k4j5n6p7q8r9s0) |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--ttl | duration | 10m | Token time-to-live (max 10m; longer TTLs silently re-open replay) |
Requires IRONFLOW_CAP_TOKEN_PRIVATE_KEY_B64 to be set.
Examples:
ironflow cloud cap-token mint clu_hooli cust_01h2g3k4j5n6p7q8r9s0ironflow cloud cap-token mint clu_hooli cust_01h2g3k4j5n6p7q8r9s0 --ttl 5mironflow cloud break-glass
Section titled “ironflow cloud break-glass”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.
ironflow cloud break-glass <cluster_id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
cluster_id | Yes | Cluster ID (e.g., clu_hooli) |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--blob-file | string | Path to encrypted blob (default: stdin) |
Requires IRONFLOW_MASTER_KEY_B64 to be set.
Examples:
# 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 fileironflow cloud break-glass clu_hooli --blob-file /tmp/clu_hooli.encironflow cloud snapshot decrypt
Section titled “ironflow cloud snapshot decrypt”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.
ironflow cloud snapshot decrypt <cluster_id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
cluster_id | Yes | Cluster ID (e.g., clu_hooli) |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--blob-file | string | Path to encrypted blob (default: stdin) | ||
--max-bytes | int64 | 268435456 (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:
# Fetch + decrypt via stdin pipeaws 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 capironflow cloud snapshot decrypt clu_hooli \ --blob-file /tmp/clu_hooli-export.enc \ --max-bytes 4294967296 > dump.tar.gzironflow circuit-breaker
Section titled “ironflow circuit-breaker”Manage circuit breakers that protect push endpoints from cascading failures. Circuit breaker state is persisted in NATS KV and shared across cluster nodes.
ironflow circuit-breaker <subcommand> [flags]Aliases: cb
ironflow circuit-breaker list
Section titled “ironflow circuit-breaker list”List all circuit breakers with their function IDs, endpoints, states, and failure counts.
ironflow circuit-breaker list [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL (default: IRONFLOW_SERVER_URL or http://localhost:9123) | |
--json | bool | false | Output as JSON |
Examples:
# List all circuit breakersironflow circuit-breaker list
# JSON outputironflow circuit-breaker list --json
# Custom serverironflow circuit-breaker list -s http://localhost:9000Output columns:
| Column | Description |
|---|---|
| FUNCTION_ID | The function that owns this circuit breaker |
| ENDPOINT | The push endpoint URL being protected |
| STATE | Current state: closed, open, or half-open |
| FAILS | Number of consecutive failures |
| LAST_FAILURE | Timestamp of the most recent failure |
ironflow circuit-breaker reset
Section titled “ironflow circuit-breaker reset”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.
ironflow circuit-breaker reset <endpoint-url | function-id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
endpoint-url | Yes* | The endpoint URL of the breaker to reset |
function-id | Yes* | The function ID of the breaker to reset |
*Provide either an endpoint URL or a function ID.
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL (default: IRONFLOW_SERVER_URL or http://localhost:9123) |
Examples:
# Reset a circuit breaker by endpoint URLironflow circuit-breaker reset https://my-app.example.com/api/handler
# Reset a circuit breaker by function IDironflow circuit-breaker reset my-function-idironflow debounce
Section titled “ironflow debounce”Inspect and cancel pending debounce entries for functions that collapse rapid-fire events into a single invocation. See the debounce how-to for background.
ironflow debounce <subcommand> [flags]Subcommands:
| Subcommand | Description |
|---|---|
list | List pending debounce entries (env-scoped) |
cancel | Cancel one pending entry without firing it |
ironflow debounce list
Section titled “ironflow debounce list”List currently-armed debounce entries scoped to the request environment. Platform-scoped credentials see all envs.
ironflow debounce list [flags]Flags:
| Long | Short | Type | Default | Description |
|---|---|---|---|---|
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL (default: IRONFLOW_SERVER_URL or http://localhost:9123) |
Examples:
ironflow debounce listironflow debounce list --jsonironflow debounce list -s http://localhost:9000Output columns: FUNCTION_ID, KEY, FIRES_AT, PERIOD_MS, EVENT_ID.
ironflow debounce cancel
Section titled “ironflow debounce cancel”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.
ironflow debounce cancel <function-id> <debounce-key> [flags]Flags:
| Long | Short | Type | Default | Description |
|---|---|---|---|---|
--env | string | Environment ID (default: resolve from entry list if unambiguous) | ||
--server | -s | string | Server 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:
# Resolve env automatically when unambiguousironflow debounce cancel my-fn-id user-42
# Explicit env for tenant-scoped clarityironflow debounce cancel my-fn-id "build:repo-7" --env env_default
# Keys with special characters round-trip fineironflow debounce cancel my-fn-id "key.with.dots"ironflow deploy
Section titled “ironflow deploy”Deploy Ironflow to a Kubernetes cluster using Helm deployment templates.
ironflow deploy [flags]Subcommands:
| Subcommand | Description |
|---|---|
upgrade | Upgrade an existing deployment |
status | Show deployment status |
delete | Delete a deployment |
ironflow deploy (initial deploy)
Section titled “ironflow deploy (initial deploy)”Deploy a new Ironflow instance to Kubernetes.
ironflow deploy [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--template | string | Deployment template: small, medium, large (required) | ||
--name | string | Helm release name (required) | ||
--namespace | -n | string | ironflow | Kubernetes namespace to deploy into |
--chart | string | Path to Helm chart directory (auto-detected if omitted) | ||
--kubeconfig | string | Path to kubeconfig file (defaults to current kubectl context) | ||
--hetzner-location | string | Hetzner 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). | ||
--set | string[] | Set Helm values (repeatable) |
Examples:
# Small deployment for dev/evaluationironflow deploy --template small --name dev
# Medium deployment for stagingironflow deploy --template medium --name staging
# Large deployment with external dependenciesironflow deploy --template large --name prod \ --set externalDatabase.url=postgres://... \ --set externalNats.url=nats://...
# Deploy to a custom namespaceironflow deploy --template medium --name staging --namespace my-ns
# Deploy with Hetzner load balancerironflow deploy --template medium --name prod --hetzner-location fsn1
# Deploy targeting a specific clusterironflow deploy --template medium --name prod \ --kubeconfig ~/.kube/clusters/hetzner-prod.yamlironflow deploy upgrade
Section titled “ironflow deploy upgrade”Upgrade an existing Ironflow deployment.
ironflow deploy upgrade [flags]Flags: Same as ironflow deploy (initial deploy).
Examples:
ironflow deploy upgrade --template medium --name stagingironflow deploy status
Section titled “ironflow deploy status”Show status of an Ironflow deployment.
ironflow deploy status [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--name | string | Helm release name (required) | ||
--namespace | -n | string | ironflow | Kubernetes namespace |
--kubeconfig | string | Path to kubeconfig file (defaults to current kubectl context) | ||
--watch | -w | bool | false | Watch pod status after showing deployment status |
Examples:
ironflow deploy status --name stagingironflow deploy status --name prod --watchironflow deploy delete
Section titled “ironflow deploy delete”Delete an Ironflow deployment.
ironflow deploy delete [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--name | string | Helm release name (required) | ||
--namespace | -n | string | ironflow | Kubernetes namespace |
--kubeconfig | string | Path to kubeconfig file (defaults to current kubectl context) |
Examples:
ironflow deploy delete --name stagingironflow emit
Section titled “ironflow emit”Emit a named event to the server. If any registered functions have triggers matching the event name, runs will be created for them.
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:
| Argument | Required | Description |
|---|---|---|
event-name | Yes | The event name (e.g., order.placed) |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--data | -d | string | Inline JSON data payload (defaults to {}) | |
--data-file | -f | string | Path to JSON file containing data payload | |
--metadata | -m | string[] | Key=value metadata pairs (repeatable) | |
--wait | -w | bool | false | Block until all matched runs complete |
--timeout | -t | duration | 30s | Max wait time (only with --wait) |
--version | int | 1 | Event schema version | |
--json | bool | false | Output as JSON instead of human-friendly text | |
--server | -s | string | Server URL override |
Data input:
Data comes from exactly one source. If multiple are detected, the command errors:
--data '{...}'— Inline JSON string--data-file path.json— Read from file- Stdin — Automatically detected when input is piped
If none are provided, data defaults to {} (empty object).
Examples:
# Emit with inline dataironflow emit order.placed --data '{"order_id": "123", "total": 99.99}'
# Emit from a fileironflow emit user.signup --data-file ./test-user.json
# Pipe from stdinecho '{"batch_id": "daily"}' | ironflow emit cron.daily
# Signal event with no dataironflow emit cache.invalidate
# Wait for all runs to completeironflow emit order.placed --data '{"order_id": "123"}' --wait
# Wait with custom timeoutironflow emit video.uploaded --data-file ./meta.json --wait --timeout 120s
# JSON output for scriptingironflow emit order.placed --data '{}' --wait --json | jq '.results[0]'
# Attach metadataironflow emit order.placed --data '{}' -m source=cli -m env=dev
# Emit with a specific event versionironflow emit order.placed --data '{"order_id": "123"}' --version 2Output (async):
Event emitted: evt_01HN8K3X5Y (order.placed)Triggered 2 run(s): run_abc123, run_def456Output (—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.
ironflow env
Section titled “ironflow env”Manage environments.
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:
| Name | ID |
|---|---|
| default | env_default |
Subcommands:
ironflow env list
Section titled “ironflow env list”List all environments with their IDs.
ironflow env list [--server URL]ironflow env create
Section titled “ironflow env create”Create a new environment.
ironflow env create <name> [--server URL] [--project PROJECT_ID]| Flag | Type | Default | Description |
|---|---|---|---|
--project | string | Project ID to associate with the environment |
Creates an isolated namespace within your Ironflow instance. The new environment starts empty — no functions, events, or runs.
ironflow env delete
Section titled “ironflow env delete”Delete an environment by ID.
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:
# List environmentsironflow env list
# Create a new environment for a specific appironflow env create my-app
# Delete a custom environmentironflow env delete env_my-appironflow event
Section titled “ironflow event”Manage event schemas and test upcasters.
ironflow event <subcommand> [flags]Subcommands:
ironflow event schema register
Section titled “ironflow event schema register”Register a JSON schema for an event type at a specific version.
ironflow event schema register <event-name> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
event-name | Yes | The event name (e.g., order.created) |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--version | int | Schema version (required) | ||
--file | string | Path to JSON schema file | ||
--schema | string | Inline JSON schema string | ||
--description | string | Schema description | ||
--server | -s | string | Server URL override |
One of --file or --schema is required. Cannot use both.
Examples:
ironflow event schema register order.created --version 1 --file schema.jsonironflow 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"ironflow event schema list
Section titled “ironflow event schema list”List registered event schemas.
ironflow event schema list [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--event | string | Filter by event name | ||
--limit | int | 100 | Maximum number of schemas to return | |
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL override |
Output:
EVENT VERSION DESCRIPTION REGISTEREDorder.created 1 Order created event 2025-01-15 12:00:05order.created 2 Added address field 2025-01-20 09:30:00Examples:
ironflow event schema listironflow event schema list --event order.createdironflow event schema list --jsonironflow event schema get
Section titled “ironflow event schema get”Get detailed information about a registered event schema.
ironflow event schema get <event-name> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
event-name | Yes | The event name to look up |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--version | int | 0 | Schema version (0 = latest) | |
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL override |
Output:
Event: order.createdVersion: 2Description: Added address fieldRegistered: 2025-01-20 09:30:00Schema:{"type":"object","properties":{"id":{"type":"string"},"address":{"type":"object"}}}Examples:
ironflow event schema get order.createdironflow event schema get order.created --version 2ironflow event schema get order.created --jsonironflow event schema delete
Section titled “ironflow event schema delete”Delete a registered event schema.
ironflow event schema delete <event-name> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
event-name | Yes | The event name to delete |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--version | int | Schema version (required) | ||
--server | -s | string | Server URL override |
Output:
Deleted schema order.created (v1)ironflow event upcast
Section titled “ironflow event upcast”Test how an event would be transformed between schema versions.
ironflow event upcast <event-name> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
event-name | Yes | The event name to upcast |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--from | int | Source version (required) | ||
--to | int | Target version (required) | ||
--data | string | Event data as JSON | ||
--data-file | string | Path to JSON file with data | ||
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL override |
Data input follows the same rules as emit (flag vs file vs stdin).
Output:
Steps applied:FROM TO DESCRIPTION1 2 added priority field
Result data:{ "orderId": "123", "customerId": "456", "priority": "normal"}Examples:
ironflow event upcast order.created --from 1 --to 2 --data '{"orderId":"123"}'ironflow event upcast order.created --from 1 --to 2 --data-file event.jsonironflow event upcast order.created --from 1 --to 3 --data '{}' --jsonironflow function
Section titled “ironflow function”List and inspect registered functions.
ironflow function <subcommand> [flags]ironflow function list
Section titled “ironflow function list”List all registered functions with their triggers and execution mode.
ironflow function list [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override | |
--json | bool | false | Output as JSON | |
--limit | int | 100 | Maximum number of functions to return |
Output:
ID TRIGGERS MODEstripe-handler stripe.payment.* pushorder-process order.created pullironflow function get
Section titled “ironflow function get”Get detailed information about a registered function.
ironflow function get <function-id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
function-id | Yes | The function ID to look up |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override | |
--json | bool | false | Output as JSON |
Output:
ID: stripe-handlerName: Stripe HandlerDescription: Handles Stripe webhook eventsMode: pushEndpoint: http://localhost:3000/api/ironflowTriggers: stripe.payment.*Examples:
ironflow function listironflow function list --jsonironflow function get stripe-handlerironflow function get stripe-handler --jsonironflow init
Section titled “ironflow init”Create a new Ironflow project from a template.
ironflow init <project-name> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
project-name | Yes | Name of the new project |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--template | -t | string | quickstart | Project template (quickstart, go-quickstart) |
--skip-install | bool | false | Skip installing dependencies | |
--module | string | Go module path for go-quickstart template |
Examples:
ironflow init my-appironflow init my-app --template go-quickstartironflow init my-app --template go-quickstart --module github.com/user/my-appironflow init my-app --skip-installironflow inspect
Section titled “ironflow inspect”Inspect a workflow run with the TUI debugger.
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:
| Argument | Required | Description |
|---|---|---|
run_id | Yes | The run ID to inspect |
Flags:
| Flag | Type | Default | Description |
|---|---|---|---|
--server | string | IRONFLOW_SERVER_URL or http://localhost:9123 | Ironflow server URL |
--dap | bool | false | Start DAP server for VS Code debugging |
--dap-port | int | 4711 | DAP server port |
--at | string | Inspect run state at a specific timestamp (ISO 8601) | |
--replay | bool | false | Step through run events frame-by-frame |
--all-events | bool | false | Include all events in replay mode (including step.started) |
Examples:
# Interactive TUI debuggerironflow inspect run_abc123
# DAP mode for VS Codeironflow inspect run_abc123 --dap
# Custom serverironflow inspect run_abc123 --server http://prod-server:9123
# Time-travel: inspect run state at a specific point in timeironflow 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.startedironflow inspect run_abc123 --replay --all-eventsironflow invoke
Section titled “ironflow invoke”Directly invoke a function by ID.
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:
| Argument | Required | Description |
|---|---|---|
function-id | Yes | The function to invoke (e.g., process-order) |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--data | -d | string | Inline JSON input data (defaults to {}) | |
--data-file | -f | string | Path to JSON file containing input data | |
--metadata | -m | string[] | Key=value metadata pairs (repeatable) | |
--no-wait | bool | false | Fire-and-forget (don’t wait for result) | |
--timeout | -t | duration | 30s | Max wait time |
--json | bool | false | Output as JSON instead of human-friendly text | |
--server | -s | string | Server URL override |
Data input follows the same rules as emit (flag vs file vs stdin, error on conflict, default {}).
Examples:
# Invoke and wait for result (default)ironflow invoke process-order --data '{"order_id": "123"}'
# Fire-and-forgetironflow invoke send-notification --data '{"user_id": "456"}' --no-wait
# With custom timeoutironflow invoke generate-report --data '{}' --timeout 120s
# Pipe from filecat complex-input.json | ironflow invoke generate-report
# JSON outputironflow invoke process-order --data '{"order_id": "123"}' --jsonOutput (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_abc123ironflow mcp
Section titled “ironflow mcp”Start the Model Context Protocol (MCP) server for AI assistant integration.
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:
| Flag | Type | Default | Description |
|---|---|---|---|
--server-url | string | http://localhost:9123 | Ironflow server URL |
--api-key | string | API key for authentication (or IRONFLOW_API_KEY) | |
--allow-writes | bool | false | Enable write operations (emit events, invoke) |
Examples:
# Start read-only MCP serverironflow mcp
# Start with write accessironflow mcp --allow-writes
# Custom server URLironflow mcp --server-url http://prod:9123 --api-key ifkey_...ironflow org
Section titled “ironflow org”Manage organizations. Create, list, get, and delete organizations.
ironflow org <subcommand> [flags]Subcommands:
| Subcommand | Description |
|---|---|
create | Create a new organization |
list | List all organizations |
get | Get organization details |
delete | Delete an organization |
ironflow org create
Section titled “ironflow org create”Create a new organization with the given name.
ironflow org create <name> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
name | Yes | Name for the new organization |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override |
Examples:
ironflow org create my-orgironflow org create my-org --server http://localhost:9000ironflow org list
Section titled “ironflow org list”List all organizations with their IDs, names, and creation dates.
ironflow org list [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL override |
Output:
ID NAME CREATEDorg_abc123 my-org 2026-01-01T00:00:00ZExamples:
ironflow org listironflow org list --jsonironflow org get
Section titled “ironflow org get”Get detailed information about an organization.
ironflow org get <id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
id | Yes | Organization ID to query |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL override |
Output:
ID: org_abc123Name: my-orgCreated At: 2026-01-01T00:00:00ZUpdated At: 2026-01-15T12:00:00ZExamples:
ironflow org get org_abc123ironflow org get org_abc123 --jsonironflow org delete
Section titled “ironflow org delete”Delete an organization by its ID.
ironflow org delete <id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
id | Yes | Organization ID to delete |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override |
Examples:
ironflow org delete org_abc123ironflow outbox
Section titled “ironflow outbox”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.
ironflow outbox <subcommand> [flags]Subcommands:
| Subcommand | Description |
|---|---|
dlq | List, requeue, or discard rows in the outbox dead-letter table |
ironflow outbox dlq list
Section titled “ironflow outbox dlq list”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.
ironflow outbox dlq list [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--env | string | Environment name (required unless IRONFLOW_ENV is set) | ||
--limit | int | 50 | Max rows to return (1-500) | |
--offset | int | 0 | Row offset for pagination | |
--json | bool | false | Output as JSON (structured for jq-based triage) | |
--server | -s | string | Server URL override |
Examples:
# Inspect the DLQ for prod, tab-formattedironflow outbox dlq list --env prod
# With IRONFLOW_ENV setIRONFLOW_ENV=prod ironflow outbox dlq list
# Structured output for scriptingironflow outbox dlq list --env prod --limit 100 --json | jq '.items[] | {event_id, topic, last_error}'ironflow outbox dlq requeue
Section titled “ironflow outbox dlq requeue”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.).
ironflow outbox dlq requeue <event-id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
event-id | Yes | The event_id of the dead-letter entry to requeue |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--env | string | Environment name (required unless IRONFLOW_ENV is set) | ||
--server | -s | string | Server URL override |
Examples:
ironflow outbox dlq requeue evt_abc123 --env prod
# Bulk requeue from a list outputironflow outbox dlq list --env prod --json \ | jq -r '.items[].event_id' \ | while read id; do ironflow outbox dlq requeue "$id" --env prod; doneironflow outbox dlq discard
Section titled “ironflow outbox dlq discard”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.
ironflow outbox dlq discard <event-id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
event-id | Yes | The event_id of the dead-letter entry to discard |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--env | string | Environment name (required unless IRONFLOW_ENV is set) | ||
--yes | bool | false | Skip the confirmation prompt | |
--server | -s | string | Server URL override |
Examples:
ironflow outbox dlq discard evt_abc123 --env prod # prompts y/Nironflow outbox dlq discard evt_abc123 --env prod --yes # non-interactiveironflow platform
Section titled “ironflow platform”Manage the Ironflow platform: users, tenants, roles, and audit log.
Requires platform credentials (via ironflow platform login) or IRONFLOW_API_KEY.
ironflow platform <subcommand> [flags]ironflow platform create-admin
Section titled “ironflow platform create-admin”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).
ironflow platform create-admin --email <email> --name <name> [flags]| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--email | string | Admin email (required) | ||
--name | string | Admin display name (required) | ||
--server | -s | string | Server URL override |
Password is read interactively from the terminal.
Examples:
ironflow platform create-admin --email admin@example.com --name "Admin"ironflow platform login
Section titled “ironflow platform login”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).
ironflow platform login --email <email> [flags]| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--email | string | Platform user email (required) | ||
--server | -s | string | Server URL override |
Examples:
ironflow platform login --email admin@example.comironflow platform login --email admin@example.com --server http://localhost:9000ironflow platform users
Section titled “ironflow platform users”Manage platform users.
ironflow platform users <subcommand> [flags]ironflow platform users list
Section titled “ironflow platform users list”List all platform users with their IDs, emails, names, and active status.
ironflow platform users list [flags]| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL override |
Examples:
ironflow platform users listironflow platform users list --jsonironflow platform users create
Section titled “ironflow platform users create”Create a new platform user with email, name, and password.
ironflow platform users create --email <email> --name <name> [flags]| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--email | string | User email (required) | ||
--name | string | User display name (required) | ||
--role-ids | []string | Role IDs to assign | ||
--server | -s | string | Server URL override |
Password is read interactively from the terminal.
Examples:
ironflow platform users create --email user@example.com --name "User"ironflow platform users create --email user@example.com --name "User" --role-ids role_abcironflow platform users delete
Section titled “ironflow platform users delete”Delete a platform user by ID.
ironflow platform users delete <id> [flags]| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override |
Examples:
ironflow platform users delete usr_abc123Platform API Keys
Section titled “Platform API Keys”Platform API keys are managed through the unified ironflow apikey command with the --platform flag. See ironflow apikey above.
# Create a platform keyironflow apikey create my-platform-key --platform
# List platform keysironflow apikey list --platform
# Rotate a platform keyironflow apikey rotate ak_abc123
# Delete a platform keyironflow apikey delete ak_abc123ironflow platform tenants
Section titled “ironflow platform tenants”Manage tenants.
ironflow platform tenants <subcommand> [flags]ironflow platform tenants list
Section titled “ironflow platform tenants list”List all tenants with their IDs, names, and creation dates.
ironflow platform tenants list [flags]| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL override |
Examples:
ironflow platform tenants listironflow platform tenants list --jsonironflow platform tenants provision
Section titled “ironflow platform tenants provision”Provision a new tenant.
ironflow platform tenants provision --name <name> [flags]| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--name | string | Tenant name (required) | ||
--server | -s | string | Server URL override |
Examples:
ironflow platform tenants provision --name my-tenantironflow platform tenants delete
Section titled “ironflow platform tenants delete”Delete a tenant by ID.
ironflow platform tenants delete <id> [flags]| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override |
Examples:
ironflow platform tenants delete tnt_abc123ironflow platform roles
Section titled “ironflow platform roles”Manage platform roles.
ironflow platform roles <subcommand> [flags]ironflow platform roles list
Section titled “ironflow platform roles list”List all platform roles with their IDs, names, and default status.
ironflow platform roles list [flags]| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL override |
Examples:
ironflow platform roles listironflow platform roles list --jsonironflow platform roles create
Section titled “ironflow platform roles create”Create a new platform role with the given name.
ironflow platform roles create <name> [flags]| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--policy-ids | []string | Policy IDs to attach | ||
--server | -s | string | Server URL override |
Examples:
ironflow platform roles create my-roleironflow platform roles create my-role --policy-ids pol_abcironflow platform roles delete
Section titled “ironflow platform roles delete”Delete a platform role by ID.
ironflow platform roles delete <id> [flags]| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override |
Examples:
ironflow platform roles delete role_abc123ironflow platform audit
Section titled “ironflow platform audit”Query the platform audit log with optional filters.
ironflow platform audit [flags]| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--event-type | string | Filter by event type | ||
--from | string | Filter events from this date (inclusive) | ||
--to | string | Filter events to this date (inclusive) | ||
--cursor | string | Pagination cursor | ||
--limit | int | 0 | Maximum number of events to return | |
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL override |
Examples:
ironflow platform auditironflow platform audit --event-type user.created --limit 50ironflow platform audit --from 2024-01-01 --to 2024-12-31 --jsonironflow policy
Section titled “ironflow policy”Manage authorization policies.
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.
ironflow policy create
Section titled “ironflow policy create”Create a new authorization policy.
ironflow policy create [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--name | string | Policy name (required) | ||
--effect | string | allow or deny (required) | ||
--actions | string | Comma-separated action patterns (required) | ||
--resources | string | Comma-separated IRN resource patterns (required) | ||
--condition | string | CEL condition expression (optional) | ||
--bypass-self-lockout-preflight | bool | false | Skip the self-lockout preflight (break-glass; audited) | |
--bypass-reason | string | Required when --bypass-self-lockout-preflight is set | ||
--server | -s | string | Server URL override |
Output:
Created policy: allow-prod-reads (id: pol_x1y2z3)ironflow policy list
Section titled “ironflow policy list”List all policies, optionally filtered by organization.
ironflow policy list [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--org | string | Filter by organization | ||
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL override |
Output:
ID NAME EFFECT ACTIONS RESOURCESpol_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:*ironflow policy get
Section titled “ironflow policy get”Get detailed information about a policy.
ironflow policy get <id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
id | Yes | Policy ID |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL override |
Output:
ID: pol_x1y2z3Name: allow-prod-readsEffect: allowActions: functions:list,runs:read,events:subscribeResources: irn:ironflow:*:*:prod:*Condition: request.environment == "prod"ironflow policy update
Section titled “ironflow policy update”Patch fields on an existing policy. Only flags you provide are sent to the server.
ironflow policy update <id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
id | Yes | Policy ID |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--name | string | New name | ||
--effect | string | New effect (allow or deny) | ||
--actions | string | New comma-separated actions | ||
--resources | string | New comma-separated resource IRNs | ||
--condition | string | New CEL condition | ||
--clear-condition | bool | false | Clear the existing CEL condition (sends empty string) | |
--bypass-self-lockout-preflight | bool | false | Skip the self-lockout preflight (break-glass; audited) | |
--bypass-reason | string | Required when --bypass-self-lockout-preflight is set | ||
--server | -s | string | Server URL override |
ironflow policy delete
Section titled “ironflow policy delete”Delete a policy by its ID.
ironflow policy delete <id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
id | Yes | Policy ID |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override |
Output:
Policy deletedironflow policy test
Section titled “ironflow policy test”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.
ironflow policy test [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--policy-id | string | Saved policy ID whose condition to test | ||
--condition | string | Inline CEL condition to test (overrides saved condition) | ||
--request | string | Request activation map as inline JSON | ||
--subject | string | Subject activation map as inline JSON | ||
--request-file | string | Path to request activation JSON file | ||
--subject-file | string | Path to subject activation JSON file | ||
--json | bool | false | Output as JSON | |
--server | -s | string | Server 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: trueironflow policy versions list
Section titled “ironflow policy versions list”Show full version history for a policy, newest first. Each row is a full snapshot for client-side diffing.
ironflow policy versions list <policy_id> [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL override |
ironflow policy rollback
Section titled “ironflow policy rollback”Forward-save a prior version’s snapshot as a new version. History is append-only — rollback never rewrites past rows.
ironflow policy rollback <policy_id> <version> [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override |
ironflow policy template list
Section titled “ironflow policy template list”List installable policy templates visible to your tenant: tenant-private bundles plus platform-published bundles.
ironflow policy template list [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL override |
ironflow policy template install
Section titled “ironflow policy template install”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).
ironflow policy template install <template_id> [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override |
Examples:
# Create an allow policy for read-only access in productionironflow 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 productionironflow 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 policiesironflow policy listironflow policy list --org org_default --json
# Update a policy's conditionironflow policy update pol_x1y2z3 --condition "subject.org == 'acme'"
# Test a policy condition without savingironflow policy test --policy-id pol_x1y2z3 \ --request '{"action":"read"}' \ --subject '{"id":"u1","roles":["admin"]}'
# Browse and roll back versionsironflow policy versions list pol_x1y2z3ironflow policy rollback pol_x1y2z3 2
# Install a template bundleironflow policy template listironflow 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 policyironflow policy delete pol_x1y2z3ironflow project
Section titled “ironflow project”Manage projects. Projects group related environments within an organization (e.g., a microservice or team boundary). The resource hierarchy is Organization → Project → Environment.
ironflow project <subcommand> [flags]Subcommands:
| Subcommand | Description |
|---|---|
create | Create a new project |
list | List all projects |
delete | Delete a project |
ironflow project create
Section titled “ironflow project create”Create a new project with the given name within the current organization.
ironflow project create <name> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
name | Yes | Name for the new project |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override |
Examples:
ironflow project create my-projectironflow project create backend-service --server http://localhost:9000ironflow project list
Section titled “ironflow project list”List all projects with their IDs, names, and creation dates.
ironflow project list [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL override |
Output:
ID NAME CREATEDproj_default_default default 2026-01-01T00:00:00ZExamples:
ironflow project listironflow project list --jsonironflow project delete
Section titled “ironflow project delete”Delete a project by its ID.
ironflow project delete <id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
id | Yes | Project ID to delete |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override |
Examples:
ironflow project delete proj_abc123ironflow projection
Section titled “ironflow projection”Manage projections: list, check status, trigger and cancel rebuilds.
ironflow projection <subcommand> [flags]Subcommands:
ironflow projection list
Section titled “ironflow projection list”List all registered projections with their mode, status, and event count.
ironflow projection list [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override | |
--json | bool | false | Output as JSON |
Output:
NAME MODE STATUS EVENTS LAST SEQ UPDATEDorders-by-customer managed active 3 1523 2m agoinventory-tracker external rebuilding 2 0 15s agoironflow projection status
Section titled “ironflow projection status”Show detailed status for a projection, including rebuild progress if one is running.
ironflow projection status <name> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
name | Yes | The projection name |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override | |
--json | bool | false | Output as JSON |
Output (active projection):
Name: orders-by-customerStatus: activeMode: managedLast Event: 1523Lag: 0Updated: 2m agoOutput (rebuilding projection):
Name: orders-by-customerStatus: rebuildingMode: managedLast Event: 0Lag: 1200Updated: 15s ago
Rebuild Job: Job ID: rebuild-abc123 Status: running Progress: 65.0% Processed: 65000 / 100000 events Started: 2m30s ago ETA: 1m15sironflow projection rebuild
Section titled “ironflow projection rebuild”Start a rebuild of a projection. Resets state and replays events from the event log.
ironflow projection rebuild <name> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
name | Yes | The projection to rebuild |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--from | string | Start replay from this event ID | ||
--to | string | Stop replay at this event ID | ||
--partition | string | Only rebuild this partition | ||
--dry-run | bool | false | Estimate work without starting rebuild | |
--server | -s | string | Server URL override | |
--json | bool | false | Output as JSON |
Output:
Rebuild startedJob ID: rebuild-abc123Projection: orders-by-customerStatus: runningTotal Events: 100000Output (—dry-run):
Dry run — rebuild not startedJob ID: rebuild-abc123Projection: orders-by-customerStatus: dry_runTotal Events: 100000Examples:
# Full rebuildironflow projection rebuild orders-by-customer
# Partial rebuild from a specific eventironflow projection rebuild orders-by-customer --from evt_123
# Rebuild a specific partitionironflow projection rebuild orders-by-customer --partition customer-123
# Preview what a rebuild would doironflow projection rebuild orders-by-customer --dry-run
# Rebuild with event rangeironflow projection rebuild orders-by-customer --from evt_123 --to evt_456ironflow projection rebuild cancel
Section titled “ironflow projection rebuild cancel”Cancel an in-progress rebuild. Previous state is preserved.
ironflow projection rebuild cancel <name> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
name | Yes | The projection to cancel rebuild for |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override |
Output:
Rebuild cancelled for projection "orders-by-customer" (status: cancelled)ironflow projection get
Section titled “ironflow projection get”Get the current state and metadata of a projection.
ironflow projection get <name> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
name | Yes | The projection name |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--partition | string | Partition key | ||
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL override |
Output:
Name: order-totalsMode: managedVersion: 15Last Event ID: evt_01HN8K3X5YLast Event At: 2m agoState: { "total_orders": 42, "total_revenue": 12500.00 }Examples:
ironflow projection get order-totalsironflow projection get order-totals --partition tenant-123ironflow projection get order-totals --jsonironflow projection pause
Section titled “ironflow projection pause”Pause a running projection. It will stop processing events until resumed.
ironflow projection pause <name> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
name | Yes | The projection name |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override |
Output:
Paused projection "order-totals" (status: paused)ironflow projection resume
Section titled “ironflow projection resume”Resume a paused projection. It will continue processing events from where it left off.
ironflow projection resume <name> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
name | Yes | The projection name |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override |
Output:
Resumed projection "order-totals" (status: active)ironflow projection delete
Section titled “ironflow projection delete”Unregister and delete a projection. Does not delete data written to external stores.
ironflow projection delete <name> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
name | Yes | The projection name |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override |
Output:
Deleted projection "old-projection"ironflow projection create
Section titled “ironflow projection create”Create a new SQL projection that builds a read model from event streams.
ironflow projection create <name> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
name | Yes | The projection name |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--sql | string | Table DDL for the projection (CREATE TABLE ...) (required unless --sql-file) | ||
--sql-file | string | Path to a file containing the table DDL (required unless --sql) | ||
--event | string[] | Event name to subscribe to (repeatable) (required) | ||
--event-handler | string[] | Per-event SQL handler in event_name=SQL format (repeatable) (required) | ||
--description | string | Projection description | ||
--json | bool | false | Output as JSON | |
--server | -s | string | Server 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:
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" \ --jsonironflow projection watch
Section titled “ironflow projection watch”Watch real-time updates for a projection via WebSocket.
ironflow projection watch <name> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
name | Yes | The projection name to watch |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | ws://localhost:9123/ws | WebSocket server URL |
--replay | -r | int | 0 | Number of historical events to replay |
--json | -j | bool | false | Output events as JSON |
--metadata | -m | bool | false | Include event metadata |
Examples:
ironflow projection watch order-totalsironflow projection watch order-totals --replay 10ironflow projection watch order-totals --jsonironflow projection wait
Section titled “ironflow projection wait”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.
ironflow projection wait <name> --min-seq <n> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
name | Yes | The projection name |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | IRONFLOW_SERVER_URL | Server URL |
--min-seq | uint64 | — | Target NATS sequence the projection must reach (required) | |
--timeout | duration | 30s | Maximum wait duration. Server caps at 60s unary, 300s with --stream. | |
--partition | string | "" | Scope wait to a single partition (managed projections) | |
--stream | bool | false | Use streaming RPC (#476) — raises the cap to 300s and emits progress + heartbeat frames so long waits survive proxies/LBs with short idle timeouts. | |
--json | bool | false | Output as JSON |
Exit codes:
| Code | Meaning |
|---|---|
0 | Projection caught up within timeout |
1 | Timed out |
2 | Error (projection not found, paused/rebuilding, bad input, network) |
Examples:
ironflow projection wait order-view --min-seq 1234ironflow projection wait order-view --min-seq 1234 --timeout 10sironflow 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 5mironflow projection wait-for-event
Section titled “ironflow projection wait-for-event”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.
ironflow projection wait-for-event <event-id> --projection <name> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
event-id | Yes | The event ID |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | IRONFLOW_SERVER_URL | Server URL |
--projection | string | — | Projection name to wait on (required) | |
--timeout | duration | 30s | Maximum wait duration. Server caps at 60s. | |
--partition | string | "" | Scope wait to a single partition (managed projections) | |
--json | bool | false | Output 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:
ironflow projection wait-for-event evt_abc --projection order-viewironflow projection wait-for-event evt_abc --projection order-view --timeout 10s --jsonironflow projection wait-batch
Section titled “ironflow projection wait-batch”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.
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:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | IRONFLOW_SERVER_URL | Server URL |
--file | string | — | Path to JSON items file, or - for stdin (required) | |
--timeout | duration | 30s | Maximum wait duration. Server caps at 60s. | |
--json | bool | false | Output as JSON |
Exit codes:
| Code | Meaning |
|---|---|
0 | All items caught up within timeout |
1 | At least one item timed out (none errored) |
2 | At least one item errored, or bad input / network |
Examples:
ironflow projection wait-batch --file items.jsonjq '...' | ironflow projection wait-batch --file - --timeout 10s --jsonironflow provision
Section titled “ironflow provision”Provision infrastructure for Ironflow (Kubernetes cluster creation).
ironflow provision <subcommand> [flags]Subcommands:
| Subcommand | Description |
|---|---|
create | Create a Kubernetes cluster |
status | Check infrastructure status |
destroy | Destroy provisioned infrastructure |
ironflow provision create
Section titled “ironflow provision create”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.
ironflow provision create [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--provider | string | Infrastructure provider: hetzner, k3d (required) | ||
--name | string | Cluster name (required). Used to name all cloud resources and the saved kubeconfig file. | ||
--template | string | Cluster size: small, medium, large (required) |
Examples:
# 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 namesironflow provision create --provider hetzner --template small --name stagingironflow 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 devironflow provision create --provider k3d --template medium --name devironflow provision status
Section titled “ironflow provision status”Check status of provisioned infrastructure.
ironflow provision status [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--provider | string | Infrastructure provider: hetzner, k3d (required) | ||
--name | string | Cluster name (required) |
Examples:
ironflow provision status --provider hetzner --name ironflowironflow provision status --provider k3d --name devironflow provision destroy
Section titled “ironflow provision destroy”Destroy provisioned infrastructure.
ironflow provision destroy [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--provider | string | Infrastructure provider: hetzner, k3d (required) | ||
--name | string | Cluster name (required) |
Examples:
ironflow provision destroy --provider hetzner --name ironflowironflow provision destroy --provider k3d --name devironflow role
Section titled “ironflow role”Manage custom roles for enterprise authorization.
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.
ironflow role create
Section titled “ironflow role create”Create a new custom role in an organization.
ironflow role create <name> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
name | Yes | Role name |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--org | string | Organization ID (required) | ||
--server | -s | string | Server URL override |
Output:
Created role: billing-team (id: role_a1b2c3d4)ironflow role list
Section titled “ironflow role list”List all roles, optionally filtered by organization.
ironflow role list [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--org | string | Filter by organization | ||
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL override |
Output:
ID NAME ORG_ID DEFAULTrole_a1b2c3d4 admin org_default truerole_e5f6g7h8 developer org_default truerole_i9j0k1l2 viewer org_default truerole_m3n4o5p6 billing org_default falseironflow role get
Section titled “ironflow role get”Get detailed information about a role.
ironflow role get <id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
id | Yes | Role ID |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL override |
Output:
ID: role_a1b2c3d4Name: billing-teamOrg ID: org_defaultDefault: falseironflow role delete
Section titled “ironflow role delete”Delete a custom role by its ID.
ironflow role delete <id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
id | Yes | Role ID |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override |
Output:
Role deletedironflow role assign-policy
Section titled “ironflow role assign-policy”Assign a policy to a role.
ironflow role assign-policy <role_id> <policy_id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
role_id | Yes | Role ID |
policy_id | Yes | Policy ID |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override |
Output:
Policy assigned to roleironflow role remove-policy
Section titled “ironflow role remove-policy”Remove a policy from a role.
ironflow role remove-policy <role_id> <policy_id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
role_id | Yes | Role ID |
policy_id | Yes | Policy ID |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override |
Output:
Policy removed from roleExamples:
# Create a custom roleironflow role create billing-team --org org_default
# List all rolesironflow role listironflow role list --org org_default --json
# Get role detailsironflow role get role_a1b2c3d4
# Assign a policy to a roleironflow role assign-policy role_a1b2c3d4 pol_x1y2z3
# Remove a policy from a roleironflow role remove-policy role_a1b2c3d4 pol_x1y2z3
# Delete a custom roleironflow role delete role_a1b2c3d4ironflow run
Section titled “ironflow run”List and inspect workflow runs.
ironflow run <subcommand> [flags]ironflow run list
Section titled “ironflow run list”List workflow runs with optional filtering.
ironflow run list [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override | |
--function | string | Filter by function ID | ||
--status | string | Filter by status (pending, running, completed, failed, cancelled) | ||
--limit | int | 50 | Maximum number of runs to return | |
--json | bool | false | Output as JSON |
Output:
ID FUNCTION STATUS STARTEDrun-1 stripe-handler completed 2025-01-15 12:00:05run-2 order-process failed 2025-01-15 11:59:30ironflow run get
Section titled “ironflow run get”Get detailed information about a specific workflow run.
ironflow run get <run-id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
run-id | Yes | The run ID to look up |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override | |
--json | bool | false | Output as JSON |
Output:
ID: run-abc123Function: stripe-handlerStatus: completedMode: pushEvent: evt_01HN8K3X5YStarted: 2025-01-15T12:00:05ZEnded: 2025-01-15T12:00:06ZDuration: 1.2sironflow run cancel
Section titled “ironflow run cancel”Cancel a running or pending workflow run.
ironflow run cancel <run-id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
run-id | Yes | The run ID to cancel |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--reason | string | Cancellation reason | ||
--server | -s | string | Server URL override |
Output:
Canceled run run-abc123 (status: cancelled)Examples:
ironflow run listironflow run list --function stripe-handler --status failedironflow run list --limit 10 --jsonironflow run get run_abc123ironflow run get run_abc123 --jsonironflow run cancel run_abc123ironflow run cancel run_abc123 --reason "no longer needed"ironflow run pause
Section titled “ironflow run pause”Pause a running workflow at the next step boundary for inspection and injection.
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:
| Argument | Required | Description |
|---|---|---|
run-id | Yes | The run ID to pause |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override |
Output:
Run run-abc123: pausedExamples:
# Pause a running workflowironflow run pause run_abc123
# Pause against a different serverironflow run pause run_abc123 --server http://prod:9123ironflow run paused-state
Section titled “ironflow run paused-state”View completed steps and their outputs for a run paused for injection.
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:
| Argument | Required | Description |
|---|---|---|
run-id | Yes | The paused run ID to inspect |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL override |
Output:
Pause reason: injectionNext step: send-notification
ID NAME INJECTED OUTPUTstep_001 validate-input {"valid":true}step_002 process-order {"order_id":"123","total":99.99}Examples:
# View paused stateironflow run paused-state run_abc123
# JSON output for scriptingironflow run paused-state run_abc123 --jsonironflow run inject
Section titled “ironflow run inject”Modify the output of a completed step while a run is paused for injection.
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:
| Argument | Required | Description |
|---|---|---|
run-id | Yes | The paused run ID |
step-id | Yes | The completed step ID to modify |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--output | string | New JSON output for the step (required) | ||
--reason | string | Reason for the injection (optional) | ||
--server | -s | string | Server URL override |
Output:
Injected step step_002Previous output: {"order_id":"123","total":99.99}Examples:
# Inject modified outputironflow run inject run_abc123 step_002 --output '{"order_id":"123","total":89.99}'
# Inject with a reason for the audit trailironflow run inject run_abc123 step_002 \ --output '{"corrected": true}' \ --reason "Fix calculation error"ironflow run resume
Section titled “ironflow run resume”Resume a paused or failed run. When resuming an injection-paused run, clears the pause state and re-dispatches from where it left off.
ironflow run resume <run-id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
run-id | Yes | The run ID to resume |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--from-step | string | Resume from a specific step ID | ||
--server | -s | string | Server URL override |
Examples:
# Resume a paused runironflow run resume run_abc123
# Resume from a specific stepironflow run resume run_abc123 --from-step step_002
# Typical scoped injection workflowironflow run pause run_abc123ironflow run paused-state run_abc123ironflow run inject run_abc123 step_002 --output '{"fixed": true}' --reason "correct value"ironflow run resume run_abc123ironflow secret
Section titled “ironflow secret”Manage encrypted secrets. Secrets are environment-scoped and write-only — values can be set but are never returned by the CLI or API.
ironflow secret list
Section titled “ironflow secret list”List all secrets in the current environment (metadata only — values are never shown).
ironflow secret list [--server URL] [--env ENV]| Flag | Short | Description | Default |
|---|---|---|---|
--server | -s | Server URL | $IRONFLOW_SERVER_URL or http://localhost:9123 |
--env | -e | Environment name | $IRONFLOW_ENV or default |
ironflow secret set
Section titled “ironflow secret set”Create or update a secret.
ironflow secret set <name> <value> [--server URL] [--env ENV] [--description DESC]| Flag | Short | Description | Default |
|---|---|---|---|
--server | -s | Server URL | $IRONFLOW_SERVER_URL or http://localhost:9123 |
--env | -e | Environment name | $IRONFLOW_ENV or default |
--description | -d | Human-readable description | (none) |
ironflow secret get
Section titled “ironflow secret get”Get metadata for a specific secret (value is never shown).
ironflow secret get <name> [--server URL] [--env ENV]| Flag | Short | Description | Default |
|---|---|---|---|
--server | -s | Server URL | $IRONFLOW_SERVER_URL or http://localhost:9123 |
--env | -e | Environment name | $IRONFLOW_ENV or default |
ironflow secret delete
Section titled “ironflow secret delete”Delete a secret.
ironflow secret delete <name> [--server URL] [--env ENV]| Flag | Short | Description | Default |
|---|---|---|---|
--server | -s | Server URL | $IRONFLOW_SERVER_URL or http://localhost:9123 |
--env | -e | Environment name | $IRONFLOW_ENV or default |
Examples:
# List secrets (metadata only)ironflow secret list
# Set a secretironflow secret set API_KEY sk-abc123 --description "OpenAI API key"
# Set a secret in a specific environmentironflow secret set DB_PASSWORD mypass --env production
# Get metadata for a secretironflow secret get API_KEY
# Delete a secretironflow secret delete API_KEYironflow serve
Section titled “ironflow serve”Start the Ironflow server with embedded NATS JetStream, database, and web dashboard.
ironflow serve [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--config | -f | string | Path to ironflow.yaml configuration file | |
--port | -p | int | 9123 | HTTP server port |
--db | -d | string | ironflow.db | SQLite database path |
--open | -o | bool | false | Open dashboard in browser after startup |
--nats-store-dir | string | (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-url | string | (none) | External NATS URL — nats://host:4222, tls://host:4222, or comma-separated seeds (or set NATS_URL). Requires PostgreSQL (IRONFLOW_DATABASE_URL). | |
--nats-creds | string | (none) | Path to NATS .creds file for JWT/NKey authentication (or set NATS_CREDS_FILE). | |
--node-id | string | (random UUID) | Stable node identifier for cluster coordination (or set IRONFLOW_NODE_ID). | |
--dev | bool | false | Enable dev mode: bypasses all authentication (API + dashboard) | |
--pprof | bool | false | Enable pprof debug endpoints on a separate listener at :6060 | |
--bootstrap-key-file | string | (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:
- Embedded NATS JetStream (messaging)
- Database — SQLite by default, PostgreSQL if
IRONFLOW_DATABASE_URLis set - Workflow engine (step execution, memoization, retry)
- PubSub bridge (real-time WebSocket event delivery)
- Consumer group manager (load-balanced event delivery)
- HTTP server with ConnectRPC API and web dashboard
Examples:
# Start with defaults (SQLite, port 9123)ironflow serve
# Custom port, open dashboardironflow serve --port 8080 --open
# PostgreSQL backendIRONFLOW_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 authenticationIRONFLOW_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 developmentironflow serve --devDev Mode
Section titled “Dev Mode”The --dev flag disables all authentication for local development:
ironflow serve --devIn 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 theadminrole - A prominent warning is shown in the startup banner
Warning: Never use
--devin production. It is a CLI flag only (no env var) to ensure it is an intentional choice on every startup.
ironflow server
Section titled “ironflow server”Server management commands.
ironflow server <subcommand> [flags]ironflow server info
Section titled “ironflow server info”Display server health, version, and runtime information.
ironflow server info [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override | |
--json | bool | false | Output as JSON |
Examples:
# Show server infoironflow server info
# JSON outputironflow server info --json
# Connect to a different serverironflow server info --server http://localhost:9000Output:
Server: http://localhost:9123Version: 0.5.0Status: healthyUptime: 2h15m0sGo: go1.25.0Functions: 3 registeredRuns: 1 activeWorkers: 2 connectedironflow sql
Section titled “ironflow sql”Execute a read-only SQL query against the Ironflow database.
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:
| Argument | Required | Description |
|---|---|---|
query | Yes | SQL SELECT query to execute |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--format | string | table | Output format: table, json, csv, jsonl | |
--timeout | int | 5000 | Query timeout in milliseconds | |
--max-rows | int | 1000 | Maximum rows to return | |
--server | -s | string | Server 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:
# Count events by nameironflow sql "SELECT name, COUNT(*) AS total FROM events GROUP BY name"
# Find failed runsironflow sql "SELECT id, status FROM runs WHERE status = 'failed' LIMIT 10"
# Export events as JSONironflow sql "SELECT * FROM events WHERE entity_id = 'order-123'" --format json
# CSV output for spreadsheetsironflow sql "SELECT id, name FROM functions" --format csv
# JSONL for streaming processingironflow sql "SELECT * FROM events" --format jsonl | jq '.name'Output (table):
id name entity_idevt_001 order.placed order-123evt_002 order.paid order-123ironflow stream
Section titled “ironflow stream”Manage entity streams for event sourcing.
ironflow stream <subcommand> [flags]Entity streams store domain events per entity with optimistic concurrency control.
Subcommands:
ironflow stream append
Section titled “ironflow stream append”Append a domain event to an entity stream.
ironflow stream append <entity-id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
entity-id | Yes | The entity ID to append the event to |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--type | string | Entity type (e.g., Order, User) | ||
--event | string | Event name (required) | ||
--data | -d | string | Event data as JSON string | |
--data-file | -f | string | Path to JSON file with event data | |
--expected-version | int64 | -1 | Expected stream version (-1=skip, 0=new, N=exact) | |
--version | int | 1 | Event schema version | |
--idempotency-key | string | Idempotency key for deduplication | ||
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL override |
Data input follows the same rules as emit (flag vs file vs stdin, error on conflict).
Examples:
# Append an eventironflow stream append order-1 --type Order --event order.placed --data '{"amount": 100}'
# Append from fileironflow stream append order-1 --type Order --event order.paid --data-file payment.json
# With optimistic concurrencyironflow stream append order-1 --type Order --event order.shipped --expected-version 2
# Pipe from stdinecho '{"status": "done"}' | ironflow stream append order-1 --type Order --event order.completedOutput:
Event appended: evt_01HN8K3X5YEntity: order-1Version: 3ironflow stream read
Section titled “ironflow stream read”Read events from an entity stream.
ironflow stream read <entity-id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
entity-id | Yes | The entity ID to read |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--from-version | int64 | 0 | Start reading from this version | |
--limit | int | 100 | Maximum number of events to return | |
--direction | string | forward | Read direction (forward or backward) | |
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL override |
Output:
VERSION NAME DATA TIMESTAMP1 order.placed {"amount":100} 2025-01-15 12:00:052 order.paid {"payment_id":"pay_123"} 2025-01-15 12:01:30Examples:
ironflow stream read order-1ironflow stream read order-1 --limit 10ironflow stream read order-1 --from-version 5 --direction backwardironflow stream read order-1 --jsonironflow stream info
Section titled “ironflow stream info”Get metadata about an entity stream.
ironflow stream info <entity-id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
entity-id | Yes | The entity ID to inspect |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL override |
Output:
Entity ID: order-1Entity Type: OrderVersion: 3Events: 3Created: 2025-01-15T12:00:05ZUpdated: 2025-01-15T12:01:30Zironflow stream list
Section titled “ironflow stream list”List entity streams with optional filtering by type.
ironflow stream list [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--type | string | Filter by entity type | ||
--limit | int | 50 | Maximum number of streams | |
--offset | int | 0 | Offset for pagination | |
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL override |
Output:
ENTITY_ID TYPE VERSION EVENTS UPDATEDorder-1 Order 3 3 2m agoorder-2 Order 1 1 5m agouser-1 User 2 2 1h agoironflow stream subscribe
Section titled “ironflow stream subscribe”Watch real-time events for an entity stream via WebSocket.
ironflow stream subscribe <entity-id> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
entity-id | Yes | The entity ID to subscribe to |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | ws://localhost:9123/ws (derived from IRONFLOW_SERVER_URL if set) | WebSocket server URL |
--replay | -r | int | 0 | Number of historical events to replay |
--json | -j | bool | false | Output events as JSON |
--metadata | -m | bool | false | Include event metadata |
Examples:
ironflow stream subscribe order-123ironflow stream subscribe order-123 --replay 10ironflow stream subscribe order-123 --jsonironflow subscribe
Section titled “ironflow subscribe”Subscribe to real-time events via WebSocket.
ironflow subscribe [patterns...] [flags]Connects to the server’s WebSocket endpoint and streams events matching the given NATS-style patterns.
Arguments:
| Argument | Required | Description |
|---|---|---|
patterns | Yes (1+) | NATS-style topic patterns to subscribe to |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | ws://localhost:9123/ws (derived from IRONFLOW_SERVER_URL if set) | WebSocket server URL |
--replay | -r | int | 0 | Number of historical events to replay |
--json | -j | bool | false | Output events as JSON (one per line) |
--metadata | -m | bool | false | Include event metadata (timestamp, sequence) |
Examples:
# Subscribe to all run eventsironflow subscribe "system.run.>"
# Subscribe to user eventsironflow subscribe "events:order.placed"
# Multiple patterns with replayironflow subscribe --replay 10 "system.run.>" "events:>"ironflow tenant
Section titled “ironflow tenant”Provision and list tenant organizations. Tenants provide multi-tenancy by atomically creating an organization, built-in roles, and a default environment.
ironflow tenant <subcommand> [flags]Subcommands:
| Subcommand | Description |
|---|---|
provision | Provision a new tenant organization |
list | List all tenants |
ironflow tenant provision
Section titled “ironflow tenant provision”Atomically create an organization, built-in roles, and a default environment.
ironflow tenant provision [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--name | string | Organization name (required) | ||
--env | string | Environment name (default: production) | ||
--server | -s | string | Server URL override |
Output:
Created org: Acme Corp (org_abc123)Created env: production (env_def456)Admin API Key: ak_abc123...Examples:
# Provision a new tenant with default environmentironflow tenant provision --name "Acme Corp"
# Provision with a custom environment nameironflow tenant provision --name "Acme Corp" --env stagingironflow tenant list
Section titled “ironflow tenant list”List all tenant organizations with their environment and key counts.
ironflow tenant list [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--json | bool | false | Output as JSON | |
--server | -s | string | Server URL override |
Output:
ID NAME ENVS KEYS CREATEDorg_abc123 Acme Corp 1 2 2026-01-01T00:00:00Zorg_def456 Widget Inc 2 3 2026-02-15T00:00:00ZExamples:
ironflow tenant listironflow tenant list --jsonironflow topic
Section titled “ironflow topic”Manage developer pub/sub topics: list topics, view statistics, and publish messages.
ironflow topic <subcommand> [flags]Topics provide lightweight service-to-service messaging without triggering functions. See the Topics guide for full details.
ironflow topic list
Section titled “ironflow topic list”List all active developer pub/sub topics.
ironflow topic list [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override | |
--json | bool | false | Output as JSON |
Output:
NAME MESSAGES CONSUMERSorder.processed 42 2user.signup 15 1ironflow topic stats
Section titled “ironflow topic stats”Show detailed statistics for a specific topic.
ironflow topic stats <topic> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
topic | Yes | Topic name (e.g., order.processed) |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override | |
--json | bool | false | Output as JSON |
Output:
Topic: order.processedMessages: 42Consumers: 2Lag: 5First Seq: 1Last Seq: 42ironflow topic publish
Section titled “ironflow topic publish”Publish a message to a developer pub/sub topic.
ironflow topic publish <topic> [flags]Arguments:
| Argument | Required | Description |
|---|---|---|
topic | Yes | Topic name (e.g., order.processed) |
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--data | -d | string | JSON data to publish | |
--data-file | -f | string | Path to JSON file with data | |
--idempotency-key | string | Idempotency key for deduplication | ||
--server | -s | string | Server 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:
# List all topicsironflow topic listironflow topic list --json
# View topic statisticsironflow topic stats order.processedironflow topic stats order.processed --json
# Publish a messageironflow topic publish order.processed --data '{"orderId": "123", "status": "shipped"}'
# Publish from fileironflow topic publish order.processed --data-file payload.json
# Publish from stdinecho '{"orderId": "123"}' | ironflow topic publish order.processed
# Publish with idempotency keyironflow topic publish order.processed --data '{"orderId": "123"}' --idempotency-key order-123-shippedironflow validate
Section titled “ironflow validate”Validate an ironflow.yaml configuration file without starting the server. Checks syntax, schema, environment variable references, and kind-specific rules.
ironflow validate [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--config | -f | string | Path 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.yamlExamples:
ironflow validate -f ironflow.yamlironflow validate -f /etc/ironflow/production.yamlironflow version
Section titled “ironflow version”Print version and build information.
ironflow versionOutput:
ironflow version v0.1.0 go: go1.25.0 os/arch: darwin/arm64ironflow webhook
Section titled “ironflow webhook”Manage webhook sources and deliveries.
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.
ironflow webhook list
Section titled “ironflow webhook list”List all registered webhook sources.
ironflow webhook list [flags]Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--server | -s | string | Server URL override | |
--json | bool | false | Output as JSON |
Output:
ID EVENT PREFIX TYPE VERIFY HEADER ALGORITHM CREATEDstripe webhook/stripe api Stripe-Signature hmac-sha256 2025-01-15 12:00:05github webhook/github sdk 2025-01-15 11:00:00ironflow webhook deliveries
Section titled “ironflow webhook deliveries”List webhook deliveries with optional filtering by provider and status.
ironflow webhook deliveries [flags]Status is color-coded: green=accepted, red=rejected/failed, yellow=deduplicated.
Flags:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--provider | string | Filter by source/provider ID | ||
--status | string | Filter by status (accepted, rejected, failed, deduplicated) | ||
--limit | int | 20 | Maximum number of deliveries to return | |
--server | -s | string | Server URL override | |
--json | bool | false | Output as JSON |
Output:
ID SOURCE STATUS EVENT ID EXTERNAL ID ERROR CREATEDdel_abc123 stripe accepted evt_def456 evt_stripe_1 2025-01-15 12:00:05del_abc124 stripe deduplicated evt_stripe_1 2025-01-15 12:00:06del_abc125 github rejected missing signature 2025-01-15 12:01:00ironflow webhook test
Section titled “ironflow webhook test”Send a test webhook delivery to the webhook endpoint.
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:
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--provider | string | Webhook provider/source ID (required) | ||
--payload | string | JSON payload to send (required) | ||
--server | -s | string | Server URL override |
Output (success):
Webhook delivered successfully (HTTP 200){ "status": "accepted", "delivery_id": "del_abc123", "event_id": "evt_def456", "run_ids": ["run_789"]}Examples:
# List webhook sourcesironflow webhook listironflow webhook list --json
# View deliveriesironflow webhook deliveriesironflow webhook deliveries --provider stripeironflow webhook deliveries --provider stripe --status rejectedironflow webhook deliveries --limit 100 --json
# Send a test webhookironflow webhook test --provider stripe \ --payload '{"type":"charge.succeeded","data":{"amount":2000}}'
# Test against a different serverironflow webhook test --provider github \ --payload '{"action":"push"}' --server http://localhost:9000Environment Variables
Section titled “Environment Variables”These are the environment variables used by CLI client commands. For server-side configuration (database, NATS, dashboard auth, etc.), see Configuration.
| Variable | Default | Description |
|---|---|---|
IRONFLOW_SERVER_URL | http://localhost:9123 | Server URL for all client commands |
IRONFLOW_API_KEY | (none) | API key sent as Authorization: Bearer header for auth |
IRONFLOW_ENV | default | Environment name for scoping queries and operations |
IRONFLOW_CONFIG_DIR | ~/.config/ironflow | Directory for storing platform credentials (credentials.json) |
LOG_LEVEL | warn (info for serve) | Log level: trace, debug, info, warn, error, fatal |