Skip to content

CLI

Frank ships two CLI surfaces. They solve different problems and should both stay documented.

ToolLocationAudiencePurpose
frankctlfrank-cli/Operators, developers, CI, agent runtimesOperate the Frank API: auth, config, sources, streams, transforms, pipelines, datasets, schedules, runs, and AI workflows.
frankutils/frank_cli/Transform pattern authorsScaffold, validate, test, and build custom transform pattern containers.

Use frankctl to control the platform. Use frank when you are building reusable transform pattern packages.

frankctl

frankctl is the TypeScript, terminal-first API client.

bash
cd frank-cli
npm install
npm run build
npm link
frankctl --help

For local Compose, the API is usually exposed on 8002:

bash
frankctl --api-url http://localhost:8002 status
frankctl config set profiles.default.apiUrl http://localhost:8002

Global options

Available on every command:

FlagPurpose
-p, --profile <name>Select config profile.
--jsonEmit machine-readable JSON when the command supports table output.
-v, --verboseVerbose logging.
-q, --quietSuppress non-error output.
--no-colorDisable ANSI colors.
--api-url <url>Override the API base URL for this invocation.

Environment variables

VariablePurpose
FRANKCTL_API_URLAPI base URL override.
FRANKCTL_KEYCLOAK_URLKeycloak base URL.
FRANKCTL_KEYCLOAK_REALMKeycloak realm.
FRANKCTL_CLIENT_IDOAuth client ID.
FRANKCTL_CLIENT_SECRETService account client secret.
FRANKCTL_PROFILEActive config profile.
FRANKCTL_TOKENRaw JWT override; bypasses token store.
FRANK_DEV_MODE=trueEnables X-Tenant-ID forwarding for local development.
FRANKCTL_TENANT_IDTenant ID forwarded when FRANK_DEV_MODE=true.
PATTERN_WEBHOOK_SECRETHMAC key for frankctl patterns register.

Exit codes

CodeMeaning
0Success.
1Generic error.
2Usage error.
3Authentication or authorization error.
4API or service error.
5Validation failed.
6CLI config missing or invalid.

Config and status

bash
frankctl status
frankctl status --json

frankctl config set profiles.default.apiUrl http://localhost:8002
frankctl config get apiUrl
frankctl config list

config get accepts effective profile fields:

text
apiUrl
keycloakUrl
realm
clientId
clientSecret

Config precedence is command flag, environment, config file, then built-in defaults.

Authentication

bash
# Browser PKCE
frankctl auth login

# Headless password grant
frankctl auth login --headless --username you@example.com --password '...'

# Service account
frankctl auth login --service-account \
  --client-id frank-api \
  --client-secret "$FRANKCTL_CLIENT_SECRET"

frankctl auth status
frankctl auth token
frankctl auth logout

Tokens are stored per profile. frankctl auth token prints a valid access token to stdout for use in scripts.

Sources

Manage source connections and source syncs.

bash
frankctl sources list [--type <pattern-id>] [--status <s>] [--search <q>] [--page N] [--page-size N]
frankctl sources get <id> [--no-streams]
frankctl sources create -f source.yaml [--name <name>] [--type <pattern-id>]
frankctl sources update <id> -f patch.yaml
frankctl sources delete <id> --yes

Discovery:

bash
frankctl sources discover <id> [--no-wait] [--timeout 300] [--poll-interval 2000]

Sync:

bash
frankctl sources sync <id> \
  [--streams customers,orders] \
  [--force-full-refresh] \
  [--no-wait] \
  [--timeout 1800] \
  [--poll-interval 3000]

Logs and history:

bash
frankctl sources history <id> [--limit 20] [--offset 0] [--status <s>]
frankctl sources logs <id> <run-id> [-f] [--level <level>] [--poll-interval 2000]

sources create and sources update read YAML, JSON, or - for stdin.

Source streams

bash
frankctl sources streams list <source-id> [--enabled-only]
frankctl sources streams set <source-id> -f streams.yaml
frankctl sources streams refresh-schema <source-id> --from-discovery [--timeout 300] [--poll-interval 2000]
frankctl sources streams refresh-schema <source-id> -f discovery.json

streams set accepts either a bare stream array or the schema accepted by the CLI's bulk stream validator. refresh-schema either consumes a saved discovery payload or runs discovery first.

Transforms

bash
frankctl transforms list [--status <s>] [--search <q>] [--pipeline-id <id>] [--page N] [--page-size N]
frankctl transforms get <id>
frankctl transforms runs <id> [--status <s>] [--limit 50] [--page N]
frankctl transforms logs <id> <run-id> [-f] [--level <level>] [--poll-interval 2000]
frankctl transforms trigger <id>

Use transforms trigger for Run Now. It posts to:

http
POST /api/v1/transforms/{id}/schedule/trigger

That endpoint is the transform "Run Now" path. It dispatches through Dagster, even for manual schedules, and returns the Dagster run information.

Pipelines

bash
frankctl pipelines list [--status <status>] [--search <q>] [--page N] [--page-size N]
frankctl pipelines get <id> [--include-version]
frankctl pipelines validate <id> [--sample-limit 1000] [--timeout 600] [--poll-interval 2500] [--no-wait]

pipelines validate starts a sandbox run and polls until terminal status unless --no-wait is supplied. It always emits final JSON to stdout. Step progress is written to stderr.

Runs

bash
frankctl runs get <workflow-id>
frankctl runs wait <workflow-id> [--timeout 600] [--poll-interval 2000]
frankctl runs cancel <id> --yes

For UUID IDs, runs cancel tries transform-run cancellation first and then source sync-run cancellation. For non-UUID IDs, it calls Temporal workflow cancellation.

Patterns

Pattern commands cover the platform's pattern catalog and external pattern lifecycle. Listing and detail commands browse source patterns; parameter validation checks transform pattern params; registration is used by CI publishing flows.

Commands:

bash
frankctl patterns list [--category <c>] [--search <q>]
frankctl patterns get <id>
frankctl patterns validate-params <pattern-id> -f params.yaml
frankctl patterns register -f webhook-payload.json

patterns register is CI-oriented and requires PATTERN_WEBHOOK_SECRET. The CLI signs the payload with X-Hub-Signature-256.

Schedules

The frankctl schedules tree is source-scoped.

bash
frankctl schedules list
frankctl schedules get <source-id>
frankctl schedules set <source-id> -f schedule.yaml
frankctl schedules pause <source-id>
frankctl schedules resume <source-id>
frankctl schedules trigger <source-id>
frankctl schedules delete <source-id> --yes

Example:

yaml
schedule_type: cron
schedule_value: "0 */6 * * *"

For transform execution, use frankctl transforms trigger <id>.

Datasets

bash
frankctl datasets list [--layer bronze|silver|gold] [--namespace <ns>] [--page N] [--page-size N]
frankctl datasets preview <layer.namespace.table> [--limit 20]
frankctl datasets snapshots <layer.namespace.table>

Dataset IDs use the dotted three-part form accepted by the FastAPI {dataset_id:path} route.

AI

All AI commands call Frank's Martha-backed AI routes and emit JSON.

bash
frankctl ai compose-pipeline -f spec.yaml [--no-wait] [--timeout 180] [--poll-interval 2500]
frankctl ai generate-transform -f spec.yaml
frankctl ai review-sql -f spec.yaml
frankctl ai fix-ci-failure -f spec.yaml
frankctl ai suggest target-schema -f spec.yaml
frankctl ai suggest field-mappings -f spec.yaml
frankctl ai suggest pattern-params -f spec.yaml
frankctl ai publish-transform -f spec.yaml

compose-pipeline starts an execution and polls /api/v1/ai/compose-pipeline/{execution_id}/status unless --no-wait is set. If the backend returns no execution_id, the CLI treats it as validation failure and does not poll.

Python frank pattern CLI

The Python frank CLI is part of utils/ and installs from the frank-shared package.

bash
cd utils
pip install -e ".[cli]"
frank --help

This tool is for authoring custom transform patterns. It does not manage deployed sources, transforms, pipelines, or runs.

Scaffold a pattern

bash
frank init <name> [--output patterns] [--template basic|sql|python]

Examples:

bash
frank init my-filter
frank init my-aggregator --template sql
frank init my-transform --output ./custom-patterns

Creates:

text
pattern.yaml
main.py
requirements.txt
Dockerfile
tests/test_transform.py
tests/sample_config.json
README.md

Validate a pattern

bash
frank validate [path] [--strict]

Validation checks:

  • pattern.yaml exists.
  • Required schema fields are present.
  • Field types match the pattern schema.
  • Pattern ID format is valid.
  • params_schema is structurally sensible.
  • Container image hints are reasonable.
  • main.py exists.

--strict fails on warnings as well as errors.

Test a pattern locally

bash
frank test [path] [--config tests/sample_config.json] [--env-file .env.test]

The test command loads a TRANSFORM_CONFIG-shaped JSON file, applies optional env vars, runs main.py, parses the emitted FrankResult, and can run Trino fixture setup/assertion/teardown blocks from the sample config.

Example config:

json
{
  "artifact_id": "test-local-001",
  "run_id": "test-run-001",
  "tenant_id": "dev-tenant",
  "source_table": "iceberg.bronze.orders",
  "target_table": "iceberg.silver.orders_clean",
  "params": {
    "filter_expression": "status != 'deleted'"
  }
}

Build a pattern image

bash
frank build [path] --tag <image-tag> [--push] [--registry ghcr.io/colivetree]

Examples:

bash
frank build patterns/my-filter --tag my-filter:v1
frank build . --tag ghcr.io/acme/my-filter:v1 --push

If the pattern directory has no Dockerfile, the CLI generates one from pattern.yaml.

Which tool should I use?

TaskTool
Log in to Frankfrankctl auth login
Create or sync a sourcefrankctl sources ...
Configure source streamsfrankctl sources streams ...
Trigger a transform runfrankctl transforms trigger <id>
Validate a pipeline sandboxfrankctl pipelines validate <id>
Preview an Iceberg datasetfrankctl datasets preview ...
Ask AI to compose or reviewfrankctl ai ...
Scaffold a custom transform patternfrank init ...
Validate a local pattern packagefrank validate ...
Run a pattern locallyfrank test ...
Build and push a pattern imagefrank build ...

Frank is built by aiaiai-pt.