Skip to content
frontal-labsPublic

About

The official command-line interface for Frontal.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

69 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Frontal Banner

Frontal CLI

The official command-line interface for the Frontal platform. Every API call goes through @frontal-labs/sdk; the CLI adds a project model (frontal.jsonc), a local dev loop and deployment workflows on top.

frontal init --name my-app
cd my-app && frontal dev          # local server, no API key needed
frontal deploy --preview          # shareable preview URL

All seven project commands are available: init, dev, types, env, deploy (+ promote/rollback), logs and policy check.

The bash blocks in this README are executed in CI (bun run test:readme). Blocks tagged skip need a real account or an interactive terminal.

Install

npm install -g frontal-cli        # Node ≥ 18
# or
brew tap frontal-labs/cli && brew install frontal-cli
# or download a single binary from the GitHub releases page

Check the install:

frontal version          # Frontal CLI v0.1.2 + runtime (bun/node, platform)
frontal --help           # grouped command overview with examples

Quick start

init creates a minimal project. It never overwrites existing files unless you pass --force.

frontal init --name my-app
cd my-app
cat frontal.jsonc

types turns frontal.jsonc into typings for your app — FrontalEnv (vars + secrets), FrontalServices (the SDK client for every enabled service) and FrontalProject:

cd my-app
frontal types
head -3 src/frontal-configuration.d.ts

The generated file starts with // Generated by frontal types — do not edit. and is regenerated in place; commit it or add it to your build.

Local development: frontal dev

dev runs a local Frontal API for the project — no API key required. Every service listed in frontal.jsonc is served from SDK-compatible fixtures persisted under .frontal/state/ (gitignored), so your app can use @frontal-labs/sdk unchanged:

cd my-app
frontal dev --port 8788 --no-watch > dev.log 2>&1 &
DEV_PID=$!
sleep 1
curl -s localhost:8788/health
curl -s -X POST localhost:8788/v1/agents -H 'content-type: application/json' \
  -d '{"name":"triage","triggers":[{"event":"ticket.created"}]}'
kill $DEV_PID

Point the SDK at it with baseUrl: "http://localhost:8787/v1" (any frt_… key works locally).

Flag Effect
--port 8787, --host 127.0.0.1 Where to listen (--port 0 picks a free port)
--scenario <name> Load .frontal/scenarios/<name>.json — { "routes": [{ "method", "path", "status", "body", "headers", "times" }] }, same shape as MockRoute in @frontal-labs/testing. Scenario routes win over built-ins
--remote ai,graph Proxy those services to the real API through the SDK (needs credentials); the rest stay local. The startup line shows [local] agents [remote] ai and proxied requests carry X-Frontal-Dev-Proxy
--persist-to <dir> State directory (default .frontal/state)
--no-watch Disable live reload of frontal*.jsonc, .env.local and scenario files
--json NDJSON lifecycle + request log (`{"type":"ready"

Built-in local services: agents (CRUD, versions, rollback, runs, SSE run stream), graph (entities, relationships, query with filter operators, neighborhood, path), datasets, blob (upload/download/list/copy/move), observability (logs query + live logs/stream fed by the server's own request log), governance (policies, access/check, compliance score). GET /health is always local and unauthenticated; every response carries an X-Request-Id. Ctrl+C shuts down cleanly.

Environment, logs and policies

env pull writes .env.local from frontal.jsonc (vars, secrets.required, apiUrl) and your active credential — never overwriting an existing file without --force, and never printing secret values. logs and policy check work against the local dev server too, so the whole loop runs without an account:

cd my-app
frontal dev --port 8789 --no-watch > dev.log 2>&1 &
DEV_PID=$!
sleep 1
frontal env pull
frontal logs --since 5m --api-url http://localhost:8789/v1
frontal policy check --api-url http://localhost:8789/v1
kill $DEV_PID
frontal env pull --env staging --force     # merge staging vars, keep existing secrets
frontal env push                           # upload vars to the current deployment
frontal logs --follow --level error        # tail (SSE), reconnects on drops
frontal logs --follow --json | jq -r .requestId
frontal policy check --strict --env prod   # warnings become errors; exit 1 on deny

Deploy, promote, rollback

deploy bundles the project's entry (default src/index.ts, via bun build) into a single ESM file and uploads it as a worker: <name>-preview for --preview (the default), <name> for --prod (confirmation required unless --yes). The URL is <apiUrl>/workers/<name>. Every deployment is recorded under .frontal/state/deploys/ with an immutable copy of the artifact, so promote and rollback re-send exactly what was deployed — no rebuild. --dry-run bundles and writes a manifest (the local state schema only, never row data) without touching the network:

cd my-app
printf 'export default { fetch: () => new Response("hi") };\n' > src/index.ts
frontal deploy --dry-run --outdir dist/frontal
cat dist/frontal/manifest.json
frontal deploy --preview                          # prints https://api.frontal.dev/v1/workers/my-app-preview
frontal promote https://api.frontal.dev/v1/workers/my-app-preview
frontal deploy --prod --yes
frontal rollback                                  # previous production artifact (+ agents listed in frontal.jsonc)

Project configuration: frontal.jsonc

{
  "$schema": "https://frontal.dev/schemas/frontal.json",
  "name": "my-app",
  "env": "dev",                      // dev | staging | prod
  "apiUrl": "https://api.frontal.dev/v1",
  "services": {
    "ai": { "remote": false },       // remote: true proxies to the API in `frontal dev`
    "agents": { "remote": false },
    "graph": { "remote": false }
  },
  "entry": "src/index.ts",           // bundled by `frontal deploy`
  "vars": { "LOG_LEVEL": "info" },   // written to .env.local by `frontal env pull`
  "secrets": { "required": ["FRONTAL_API_KEY"] }
}
  • Comments and trailing commas are allowed. The $schema URL gives editors validation and completions; the schema is generated from the CLI's own validator (schemas/frontal.json, bun run generate:schema).
  • Unknown service keys fail validation with the list of valid services (agents, ai, audit, auth, billing, blob, connectors, data, datasets, events, governance, graph, integrations, lineage, observability, ontology, pipelines, sandbox, schedules, webhooks, workers, workflows).
  • Per-environment overlays: frontal.staging.jsonc is deep-merged over frontal.jsonc when you pass --env staging (or when env is set to staging).
  • Connection rules (apiUrl, optional sdk.timeout/maxRetries/retryDelay/headers) are validated with the SDK's own schema.

Authentication

Credentials resolve in this order: --api-key → FRONTAL_API_KEY → .env.local in the project → the active profile in ~/.frontal/config.json (API key, then OAuth session).

frontal auth login                 # browser OAuth (PKCE)
frontal auth login --method api-key
frontal auth whoami                # local status + account profile
frontal auth whoami --local        # no API call

Set FRONTAL_CONFIG_DIR to relocate the profile store (CI, tests).

Commands

Command Purpose
frontal init [--name <dir>] [--force] Create frontal.jsonc, .env.example, .gitignore entries, src/
frontal dev [--port] [--scenario] [--remote] [--persist-to] Local Frontal API backed by .frontal/state
frontal types [--out <file>] Generate FrontalEnv / FrontalServices / FrontalProject typings
frontal deploy [--preview|--prod] [--yes] [--dry-run --outdir <dir>] Bundle + upload a worker; print its URL
frontal promote <url> / frontal rollback [url] Re-point production at a recorded artifact (no rebuild)
frontal env pull [file] [--force] / frontal env push [file] .env.local from frontal.jsonc + credentials / upload vars to the current deployment
frontal logs [--follow] [--filter <q>] [--since 15m] [--level <l>] Query or tail platform logs (SSE)
frontal policy check [--strict] [--user] [--role] Dry-run governance: policy files, deploy access per service, compliance
frontal auth <login|password-login|signup|logout|whoami|token|refresh|mfa> Sessions, API keys, MFA
frontal config <set|get|list|reset|profiles|use|telemetry> Profiles in ~/.frontal
frontal workflows <list|create|search|batch|run get|run summary|run timeline> Workflows and executions (SSE timeline)
frontal runs <list|create> Runs
frontal invocations create Submit an invocation
frontal events <list|get|query|usage|reprocess> Events
frontal completion <bash|zsh|fish> Shell completions
frontal migrate-legacy v1 → current command mapping

See llms.txt for a machine-readable summary of every command.

Every command has an Examples: section in --help:

frontal workflows list --help

Global flags

Flag Effect
--json / --yaml Machine-readable output (secrets are always redacted)
--env <dev|staging|prod> Select the environment overlay and X-Frontal-Environment
--api-key <key>, --api-url <url> Override credentials / base URL for one call
-p, --profile <name> Use a named profile
-q, --quiet, -v, --verbose, --debug Output verbosity (--verbose logs every request)
-y, --yes Skip confirmation prompts (CI)
--watch [seconds], --until field=value Re-run a read command until a condition holds

Examples

frontal workflows list --limit 10 --json | jq '.data[].name'
frontal workflows run timeline wf_123 run_456 --json | jq .data
frontal events query --body '{"type":"agent.run.completed"}'

Errors

Every failure prints a stable code, a fix hint, a docs link and the request id, and exits with a stable code — the same fields are in --json output on stderr:

cd my-app
frontal workflows list --api-url http://127.0.0.1:9/v1 --json || echo "exit code: $?"
# stderr: {"error":{"code":"NETWORK_ERROR","message":"Could not reach the Frontal API.","fix":"…","docs":"…"}}
# stdout: exit code: 10
Exit Meaning
0 Success
1 General error
2 Validation error (bad input / payload)
3 Authentication error (NO_CREDENTIALS, UNAUTHORIZED, TOKEN_EXPIRED)
4 Permission denied
5 Not found
6 Configuration error (CONFIG_INVALID, NO_PROJECT)
10 / 11 / 12 Network / timeout / rate limited

Environment variables

Variable Purpose
FRONTAL_API_KEY API key (frt_…)
FRONTAL_API_URL API base URL (default https://api.frontal.dev/v1)
FRONTAL_ENV development / test / production for the SDK; the CLI maps --env dev|staging|prod
FRONTAL_DEBUG 1 to log every request (same as --verbose)
FRONTAL_PROFILE Profile name (same as --profile)
FRONTAL_CONFIG_DIR Location of the profile store (default ~/.frontal)

Development

bun install
bun run dev -- --help          # run from source
bun run build                  # dist/index.js (npm bin, Node ≥ 18)
bun run build:binary           # dist/frontal single executable (bun build --compile)
bun run type-check && bun run test && bun run lint
bun run test:readme            # execute the bash blocks in this README

See docs/DEVELOPERS.md for the architecture and CONTRIBUTING.md for the workflow.

License

Apache License 2.0 - see LICENSE.md and NOTICE.md.

Support

Changelog

See CHANGELOG.md for version history and changes.

About

The official command-line interface for Frontal.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages